Exception running application when adding insights to application using Application Insights Status Monitor Preview - azure-application-insights

I'm playing around with the preview, and tried adding insights to a IIS web application deployed locally on my machine. It's a .Net 4.5 application running in a nothing out of the ordinary application pool. When starting the application after adding insights, I get this exception:
Could not load file or assembly 'Microsoft.ApplicationInsights.Extensions.Intercept_x64.dll' or one of its dependencies. The module was expected to contain an assembly manifest.
I tried "Enable 32-Bit Applications" to both true and false with no difference in result.
Has anyone experienced a similar error?

Unfortunately ASP.NET tries to load literally everything that is in \bin as managed assemblies
Microsoft.ApplicationInsights.Extensions.Intercept_x64.dll is not a managed assembly, but ASP.NET Web App should not fail with yellow page in this case, you would see it only in FusLogvw.
Do you use any web publishing?
Did you precompile your web site on publish?
Could you provide full stack trace of the exception?

I've just come across this issue, and after a few hours found it was due to a conflict with FluentSecurity.
It's detailed here: https://github.com/kristofferahl/FluentSecurity/issues/70
The work-around was to add the following lines just before calling SecurityConfigurator.Configure():
SecurityDoctor.Current.EventListenerScannerSetup = scan =>
{
scan.ExcludeAssembly(file => Path.GetFileName(file).Equals("Microsoft.ApplicationInsights.Extensions.Intercept_x64.dll"));
scan.ExcludeAssembly(file => Path.GetFileName(file).Equals("Microsoft.ApplicationInsights.Extensions.Intercept_x86.dll"));
};
Hope this helps somebody else.

My inner exception pointed to WebActivator. So I Uninstall-Package WebActivator -Force, added the appropriate calls in Application_Start and all was good again.

I'm still testing this but I think I've resolved this problem....
The solution is based on the same solution as the SQL Spatial Types native .dll solution; if you know this you'll see the similarity between this and that package.
Step 1
Go Create a new subdirectory in the MVC project and under this two more sub-directories; I used :
MVCRoot ---> ApplicationInsights/x86
---> ApplicationInsights/x64
Under each directory add a linked item from the package directory, this was :
../packages\Microsoft.Diagnostics.Instrumentation.Extensions.Intercept.0.12.0-build02810\lib\native\x64\Microsoft.ApplicationInsights.Extensions.Intercept_x64.dll
and
../packages\Microsoft.Diagnostics.Instrumentation.Extensions.Intercept.0.12.0-build02810\lib\native\x86\Microsoft.ApplicationInsights.Extensions.Intercept_x86.dll
respectively.
I then add this code in a file in the 'root' of the AppplicationInsights folder called loader.cs which looked like this:
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace ApplicationInsights
{
/// <summary>
/// Utility methods related to CLR Types for SQL Server
/// </summary>
internal class Utilities
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);
/// <summary>
/// Loads the required native assemblies for the current architecture (x86 or x64)
/// </summary>
/// <param name="rootApplicationPath">
/// Root path of the current application. Use Server.MapPath(".") for ASP.NET applications
/// and AppDomain.CurrentDomain.BaseDirectory for desktop applications.
/// </param>
public static void LoadNativeAssemblies(string rootApplicationPath)
{
var nativeBinaryPath = IntPtr.Size > 4
? Path.Combine(rootApplicationPath, #"ApplicationInsights\x64\")
: Path.Combine(rootApplicationPath, #"ApplicationInsights\x86\");
CheckAddDllPath(nativeBinaryPath);
// LoadNativeAssembly(nativeBinaryPath,
// IntPtr.Size > 4
// ? "Microsoft.ApplicationInsights.Extensions.Intercept_x64.dll"
// : "Microsoft.ApplicationInsights.Extensions.Intercept_x86.dll");
}
public static void CheckAddDllPath(string dllPath)
{
// find path to 'bin' folder
var pathsToAdd = Path.Combine(new string[] { AppDomain.CurrentDomain.BaseDirectory, dllPath });
// get current search path from environment
var path = Environment.GetEnvironmentVariable("PATH") ?? "";
// add 'bin' folder to search path if not already present
if (!path.Split(Path.PathSeparator).Contains(pathsToAdd, StringComparer.CurrentCultureIgnoreCase))
{
path = string.Join(Path.PathSeparator.ToString(), new string[] { path, pathsToAdd });
Environment.SetEnvironmentVariable("PATH", path);
}
}
private static void LoadNativeAssembly(string nativeBinaryPath, string assemblyName)
{
var path = Path.Combine(nativeBinaryPath, assemblyName);
var ptr = LoadLibrary(path);
if (ptr == IntPtr.Zero)
{
throw new Exception(string.Format(
"Error loading {0} (ErrorCode: {1})",
assemblyName,
Marshal.GetLastWin32Error()));
}
}
}
}
I then added this to the global.asax this so:
protected override void Application_Start(object sender, EventArgs e)
{
ApplicationInsights.Utilities.LoadNativeAssemblies(Server.MapPath("~/bin"));
}
So far it seems to be passed events so far as I can tell. All come back and update this should I find a problem with what I've done.
At least the MVC application now starts :-)
UPDATE: This is not the end of the story :-(
I had to also modify the Microsoft.Diagnostics.Instrumentation.Extensions.Intercept.props file which is under the build directory of the package to make it not include the files into the bin directory.
When I was done it looked like this :
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)\..\lib\native\x86\Microsoft.ApplicationInsights.Extensions.Intercept_x86.dll">
<CopyToOutputDirectory>None</CopyToOutputDirectory>
</None>
<None Include="$(MSBuildThisFileDirectory)\..\lib\native\x64\Microsoft.ApplicationInsights.Extensions.Intercept_x64.dll">
<CopyToOutputDirectory>None</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
I've had to check in this package into my source control system as I think I'm now going to be faced with the problem with Continuous Build restoring a fresh copy of the package which I don't want.
I can't wait for MS to come up with a proper fix for this.

I've just deleted everything in my /bin folder and it seemed to have resolved the issue. Not sure what happen or anything, it's a project i haven't touched in ages. But it solved it :)

Related

Xamarin Amazon IAP error using D8+R8 with Proguard in Release Failing but working Debug

I am using AmazonIapV2Android.dll provided by Amazon team for the Xamarin.Android project. I have implemented it last year and have been using successfully with Dx+proguard with using proguard rules as below. Those lines are also suggested by Amazon documentation. see the link
-dontwarn com.amazon.**
-keep class com.amazon.** {*;}
-keepattributes *Annotation*
Recently I have changed my xamarin.android project using d8+r8 using the same proguard file. Everything, google iap implementation also fine but Amazon IAP started throwing exception.
Jsonable.CheckForErrors
(System.Collections.Generic.Dictionary`2[TKey,TValue] jsonMap)
com.amazon.device.iap.cpt.AmazonException: java.lang.RuntimeException:
Missing type parameter.
at com.amazon.device.iap.cpt.RequestOutput.CreateFromJson
(System.String jsonMessage) [0x0002d] in
<26520843ea114e5a91256077e0412906>:0 \n at
com.amazon.device.iap.cpt.AmazonIapV2Impl+AmazonIapV2Base.GetProductData
(com.amazon.device.iap.cpt.SkusInput skusInput) [0x00013] in
I am using also linker as User and sdk assemblies, this is triggering obfuscation obviously and some methods are removed by the linker because using Sdk assemblies only or No Linking, everything works fine.
I have added the AmazonIapV2Android as linker to skip but it didnt help.
When I check the code implementation of the RequestOutput.CreateFromJson function implementation, it looks like as below.
using com.amazon.device.iap.cpt.json;
namespace com.amazon.device.iap.cpt
{
public sealed class RequestOutput : Jsonable
{
public string RequestId{get;set;}
public static RequestOutput CreateFromJson(string jsonMessage)
{
try
{
Dictionary<string, object> jsonMap = Json.Deserialize(jsonMessage) as Dictionary<string, object>;
Jsonable.CheckForErrors(jsonMap);
return CreateFromDictionary(jsonMap);
}
catch(System.ApplicationException ex)
{
throw new AmazonException("Error encountered while UnJsoning", ex);
}
}
and implementation for Jsonable in the dll looks as below
namespace com.amazon.device.iap.cpt
{
public abstract class Jsonable
{
public static Dictionary<string, object> unrollObjectIntoMap<T>(Dictionary<string, T> obj) where T:Jsonable
{
Dictionary<string, object> jsonableDict = new Dictionary<string, object>();
foreach (var entry in obj)
{
jsonableDict.Add (entry.Key, ((Jsonable)entry.Value).GetObjectDictionary());
}
return jsonableDict;
}
public static List<object> unrollObjectIntoList<T>(List<T> obj) where T:Jsonable
{
List<object> jsonableList = new List<object>();
foreach (Jsonable entry in obj)
{
jsonableList.Add(entry.GetObjectDictionary());
}
return jsonableList;
}
public abstract Dictionary<string, object> GetObjectDictionary();
public static void CheckForErrors(Dictionary<string, object> jsonMap)
{
object error;
if (jsonMap.TryGetValue("error", out error))
{
throw new AmazonException(error as string);
}
}
}
}
I have tried to use linker.xml with settings like below also but it didnt help either.
<assembly fullname="AmazonIapV2Android">
<namespace fullname="com.amazon.device.iap.cpt" />
<namespace fullname="com.amazon.device.iap.cpt.log" />
<namespace fullname="com.amazon.device.iap.cpt.json" />
</assembly>
I cannot figure out why should throw exception while i am defining keepclass for all methods and members under the namespace starting with com.amazon prefix.
Any idea what could be the reason here?
EDIT: just had several more tests and my initiale comment was slightly wrong. strange way app is working in debug with Linker set "SDK assemblies only" but in release it doesnt work even with "SDK assemblies only"
Obviously this is a known problem for using R8 and Amazon IAP. Typical amazon doesnt care and update their package. especially there is no update for Xamarin IAP since 2016.
Here are the links to problem
https://forums.developer.amazon.com/questions/205480/in-app-billing-not-working-since-android-studio-de.html
https://issuetracker.google.com/issues/134766810
Currently there are 3 workarounds,
disable r8. Bad is that no obfuscation, no optimization.
Use dx+proguard+multi dex instead of d8+r8. There is a problem here if you use androidx, androidx libraries dont work with dx+proguard, they work only with d8+r8, you need to go back to support libraries.
I am not sure but amazon website claims that it is claimed, it works with r8 but this is pobably for the android java library not for xamarin. Because as i cheked there is newer version to as jar. You can theoretically use Binding library to get a new dll and try but I read even for Android studio projects, this doesnt work. So i tried to create a binding library and it had many errors and api seems to be different than xamarin. It is a lot of effort for non-profitable app store.
here is the link to github issue on xamarin.android as well.

.NET Core Error 1053 the service did not respond to the start or control request in a timely fashion

I created a Windows Service starting from my .NET Core project following this
After this, I installed correctly it on my working machine and started it.
This is my service class:
using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading.Tasks;
namespace xxx
{
public class WindowsService
{
static void Main(string[] args)
{
System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
using (var service = new Service())
{
ServiceBase.Run(service);
}
}
}
internal class Service : ServiceBase
{
public Service()
{
ServiceName = "...";
}
protected override void OnStart(string[] args)
{
try
{
base.OnStart(args);
Task.Run(() => xxxx);
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
protected override void OnStop()
{
base.OnStop();
}
protected override void OnPause()
{
base.OnPause();
}
}
}
So, I copied the file and installed it also on a server. Here, when I try to start it, I get:
After this, I start a lot of googling... for example, I tried the following steps :
Go to Start > Run > and type regedit
Navigate to: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
With the control folder selected, right click in the pane on the right and - select new DWORD Value
Name the new DWORD: ServicesPipeTimeout
Right-click ServicesPipeTimeout, and then click Modify
Click Decimal, type '180000', and then click OK
Restart the computer
The weird point here is that the voice ServicesPipeTimeout didn't exist and I created it. Comparing the server with my working machine, there are also other value not present in the server. They are:
ServicesPipeTimeout
OsBootstatPath
Here the screenshot of regedit from the server:
Are these relevant?
I also tried to reinstall the service, recompile my files... how can I fix this problem? The error appears immediatly, it doesn't wait any timeout!
I had this problem when I switched my project to another location.
When I moved the project, I had copied the files in bin/debug folder too. The issue was resolved after I cleared the debug folder and created a new build.
See if this works!
It's a bit old question but someone may find this useful.
So I had the following code in Program.cs:
builder.SetBasePath(Environment.CurrentDirectory).AddJsonFile("appsettings.json")
Changed it to:
builder.SetBasePath(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)).AddJsonFile("appsettings.json")
This seemed to fix the problem for me.
The problem with this error is that it is super generic.
Hopefully MS will give us some log in the future.
if you check the windows event viewer under applications it tells you what exactly is the exception that causes this error.
in my case the problem was i published the service in net6 and tried to run it on a pc with net7 installed. apparently it requires the exact major version that was used to publish the app.

XUnit Net Core Web API Integration Test: "The ConnectionString property has not been initialized."

Just trying to build an Integration Test project for a NET Core Web API.
So I've followed a few examples, including this one (https://dotnetcorecentral.com/blog/asp-net-core-web-api-integration-testing-with-xunit/) and naturally, I run into issues. When I run the simple GET test I get an exception:
"System.InvalidOperationException : The ConnectionString property has not been initialized."
Any help would be appreciated.
For server = new TestServer(new WebHostBuilder().UseStartup<Startup>());, you need to manually configure the appsettings.json path like
var server = new TestServer(WebHost.CreateDefaultBuilder()
.UseContentRoot(#"D:\Edward\SourceCode\AspNetCore\Tests\IntegrationTestMVC")
// This is the path for project which needs to be test
.UseStartup<Startup>()
);
For a convenience way, I would suggest you try Basic tests with the default WebApplicationFactory.
The WebApplicationFactory constructor infers the app content root path by searching for a WebApplicationFactoryContentRootAttribute on the assembly containing the integration tests with a key equal to the TEntryPoint assembly System.Reflection.Assembly.FullName. In case an attribute with the correct key isn't found, WebApplicationFactory falls back to searching for a solution file (*.sln) and appends the TEntryPoint assembly name to the solution directory. The app root directory (the content root path) is used to discover views and content files.
Reference:How the test infrastructure infers the app content root path
I had to override CreateHostBuilder in my derived WebApplicationFactory in order to add the configuration for the connection string (since it was read from user secrets).
public class CustomApplicationFactory : WebApplicationFactory<Sedab.MemberAuth.Startup>
{
protected override IHostBuilder CreateHostBuilder()
{
var initialData = new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("ConnectionStrings:DefaultConnection", "test")
};
return base.CreateHostBuilder().ConfigureHostConfiguration(config => config.AddInMemoryCollection(initialData));
}
}

EFCore SQLite connection string with relative path in asp.net

I have just added SQLite to my asp.net webApi project, and am having trouble working out how get the path to the App_Data folder to pass to DbContextOptionsBuilderUseSqlite
I have the following in the web.config I have a link to an external a config file with the conenction string...
<connectionStrings configSource="config\connectionStrings.config"/>
and in there I have...
<connectionStrings>
<add name="MyDatastore"
connectionString="DataSource=./App_Data/test.sqlite" />
</connectionStrings>
And in my DbContext.OnConfiguring I Have....
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string path = WebConfigurationManager.ConnectionStrings["MyDatastore"].ConnectionString;
optionsBuilder.UseSqlite(path);
}
}
The path is correctly retrieved (I can see I get the path as configured on connectionStrings.config
so ./App_Data/test.sqlite is passed to optionsBuilder.UseSqlite(path).
However, I get the following error...
SQLite Error 14: 'unable to open database file'.
If I use just connectionString="DataSource=test.sqlite" /> then it seems to magically find the file in the App_Data folder, when I ran on my dev machine in debug, but I had problems on another machine (release build). I assume it is the path, though all I get back is 'unable to open database file'.
I also tried..
connectionString="DataSource=|DataDirectory|test.sqlite" />
This gives me a Illegal characters in path error.
The following does work (full path)
connectionString="d:\0\test.sqlite" />
But I want to be able to use relative paths, eg maybe even .\datastore\test.sqlite.
Does any one have any ideas on this?
Thanks in advance
You'll have to fix up the relative paths at runtime:
var builder = new SqliteConnectionStringBuilder(connectionString);
builder.DataSource = Path.GetFullPath(
Path.Combine(
AppDomain.CurrentDomain.GetData("DataDirectory") as string
?? AppDomain.CurrentDomain.BaseDirectory,
builder.DataSource);
connectionString = builder.ToString();
Works perfectly for me.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var dataSource = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "siteDB.db");
optionsBuilder
.UseSqlite($"Data Source={dataSource};");
}
Note: This solution was tested for .Net Core 5, and one can presume it will work on 2.x, 3.x, 5
If you want to use a diferent project than the one provided when you started, you have to specify the correct path ("Data Source = ..\\MyApplication.DAL\\sqliteDatabase.db") in the appsettings.json.
In this presented case, you don't even need to write the method OnConfiguring(DbContextOptionsBuilder optionsBuilder) in the ApplicationDbContext.cs.
You have a full setup bellow (Startup & appsettings.json).
My project structure:
-> MyApplication (solution)
-> MyApplication.UI (initial project of the solution)
-> MyApplication.BL (project)
-> MyApplication.DAL (project)
Inside Startup.cs
public void ConfigureServices(IServiceCollection services)
{
//... other services
services.AddDbContext<ApplicationDbContext>
(x => x.UseSqlite(Configuration.GetConnectionString("SqliteConnection")));
//.... other services and logic
}
In appsettings.json :
"ConnectionStrings": {
"SqliteConnection": "Data Source = ..\\MyApplication.DAL\\sqliteDatabase.db"
}
Works for me on linux, .net core 5.
var builder = new SqliteConnectionStringBuilder("Data Source=MyDatabase.db");
builder.DataSource = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, builder.DataSource);
services.AddDbContext<MyContext>(o => o.UseSqlite(builder.ToString());
Assumes database is in the bin directory, e.g. MyProject/bin/Debug/MyDatabase.db or MyProject/bin/Release/MyDatabase.db.
If you are a .Net Core backend developer who use sqlite, make sure to use below code example. Otherwise SQLite Error 14: 'unable to open database file' error will come.
Startup.cs
var baseDirectory = System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
string dbPathSystemLog = Path.Combine(baseDirectory, "CAMSCoreSystemLog.db");
SystemLogDBContext.cs
public class SystemLogDBContext : DbContext
{
public SystemLogDBContext(DbContextOptions<SystemLogDBContext> options) : base(options)
{
Database.EnsureCreated();
}
}
This line will create the Db if not exist
Database.EnsureCreated();
I was struggling two days. This will help someone.

ASP.NET 5, EF 7 and SQLite - SQLite Error 1: 'no such table: Blog'

I followed the Getting Started on ASP.NET 5 guide about Entity Framework 7 and I replaced MicrosoftSqlServer with Sqlite, the only difference in the code is in Startup.cs:
services.AddEntityFramework()
.AddSqlite()
.AddDbContext<BloggingContext>(options => options.UseSqlite("Filename=db.db"));
When I run the website and navigate to /Blogs, I get an error:
Microsoft.Data.Sqlite.SqliteException was unhandled by user code
ErrorCode=-2147467259 HResult=-2147467259 Message=SQLite Error 1:
'no such table: Blog' Source=Microsoft.Data.Sqlite
SqliteErrorCode=1 StackTrace:
at Microsoft.Data.Sqlite.Interop.MarshalEx.ThrowExceptionForRC(Int32 rc,
Sqlite3Handle db)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior
behavior)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior
behavior)
at System.Data.Common.DbCommand.ExecuteReader()
at Microsoft.Data.Entity.Query.Internal.QueryingEnumerable.Enumerator.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.d__1`2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at Microsoft.Data.Entity.Query.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at EFGetStarted.AspNet5.Controllers.BlogsController.Index() in d:\arthur\documents\visual studio
2015\Projects\EFGetStarted.AspNet5\src\EFGetStarted.AspNet5\Controllers\BlogsController.cs:regel
18 InnerException:
I understand this as if there is no table called 'Blog', but when I open the .db file in DB Browser for SQLite, there actually is a table called 'Blog':
Does SQLite require other changes in the code, or is this an error in the SQLite connector for Entity Framework?
It is very likely the database actually being opened by EF is not the file you are opening in DB Browser. SQLite use the process current working directory, which if launched in IIS or other servers, can be a different folder than your source code directory. (See issues https://github.com/aspnet/Microsoft.Data.Sqlite/issues/132 and https://github.com/aspnet/Microsoft.Data.Sqlite/issues/55).
To ensure your db file is in the right place, use an absolute path. Example:
public class Startup
{
private IApplicationEnvironment _appEnv;
public Startup(IApplicationEnvironment appEnv)
{
_appEnv = appEnv;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddSqlite()
.AddDbContext<MyContext>(
options => { options.UseSqlite($"Data Source={_appEnv.ApplicationBasePath}/data.db"); });
}
}
I did this and was still having trouble loading the database. I added the following code in the constructor for the database context:
Database.EnsureCreated();
Now my context file looks like this:
It created a new database on my new Azure hosting site, so if you have a lot of existing data to migrate, this won't work. It worked for me so figured I'd share.
Taken from EF Core documentation...
Run from Visual Studio
To run this sample from Visual Studio, you must set the working
directory manually to be the root of the project. Ifyou don't set the
working directory, the following Microsoft.Data.Sqlite.SqliteException
is thrown: SQLite Error 1: 'no such table: Blogs'.
To set the working directory:
In Solution Explorer, right click the project and then select Properties.
Select the Debug tab in the left pane.
Set Working directory to the project directory.
Save the changes.
I had this issue on netcoreapp2.0. There's a related issue that may be at fault, but I didn't want to solve it by going to a nightly build.
The solution for me was to create and pass an SqliteConnection instead of using the builder string.
So for this setup:
string id = string.Format("{0}.db", Guid.NewGuid().ToString());
var builder = new SqliteConnectionStringBuilder()
{
DataSource = id,
Mode = SqliteOpenMode.Memory,
Cache = SqliteCacheMode.Shared
};
Compose for the DI like so:
var connection = new SqliteConnection(builder.ConnectionString);
connection.Open();
connection.EnableExtensions(true);
services.AddDbContext<SomeDbContext>(options => options.UseSqlite(connection));
The error I had was using this style of init:
services.AddDbContext<SomeDbContext>(options => options.UseSqlite(builder.ConnectionString));
My scaffolding also has a one-time call to:
var dbContext = serviceScope.ServiceProvider.GetService<SomeDbContext>();
dbContext.Database.OpenConnection();
dbContext.Database.EnsureCreated();
Using this approach all my DI-instantiated copies of SomeDbContext would all point at a valid SQLite db, and that db would have auto-created schema as per my entities.
Looks like things have changed because IApplicationEnvironment has been replaced with IHostingEnvironment.
Removing IApplicationEnvironment \ IRuntimeEnvironment
public class Startup
{
private IHostingEnvironment _appHost;
public Startup(IHostingEnvironment appHost)
{
_appHost = appHost;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkSqlite()
.AddDbContext<MyContext>(
options => { options.UseSqlite($"Data Source={_appHost.ContentRootPath}/data.db"); });
}
}
I Had the same problem and I found the answer in this link:
https://www.youtube.com/watch?v=yRmMYrSROPs
Just update your database via command:
dotnet ef update database
you can set up the configuration adding;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source = path//DatabaseName.db");
}
the example uses SQLite, but you can choose your own DB.
If you have multiple DataContexts, the EnsureCreated method will only work on the first call. See its documentation:
If the database exists and has any tables, then no action is taken
To create tables of additional DataContexts, use
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator) secondDbContext.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();

Resources