CirrusRedOrg / EntityFrameworkCore.Jet

Entity Framework Core provider for Access database
MIT License
139 stars 38 forks source link

efcore.jet 2.2.0 database provider error. #35

Open Weijee opened 4 years ago

Weijee commented 4 years ago

I want to use efcore.jet 2.2.0 in my asp.netcore 2.2.0 project. But I got a exception as below:

System.InvalidOperationException: 'No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.'

My Connection String is

"ConnectionStrings": {
    "MSAccessConnection": "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\********\\db\\test.mdb;"
  }

"ConfigureServices" Method:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });
    services.AddDbContext<TestDbContext>(options => 
        options.UseJet(Configuration.GetConnectionString("MSAccessConnection")));
    services.AddScoped<UserDAO, UserDAO>();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Any one can help me? Is there any Samples?

bubibubi commented 4 years ago

Probably you can find an answer faster asking on stack overflow.

lauxjpn commented 4 years ago

System.InvalidOperationException: 'No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.'

If you use ASP.NET and register your DbContext with services.AddDbContext<TestDbContext>(), then you should use dependency injection to get an instance of your context.

So do not use code like the following:

public class MyController : ControllerBase
{
    public async Task<ActionResult<int>> GetIceCreamCount()
    {
        // This will throw with your example code.
        using (var dbContext = new TestDbContext())
        {
            var iceCreams = _dbContext.IceCreams.ToListAsync();
            return iceCreams.Count;
        }
    }
}

Instead do something like the following:

public class MyController : ControllerBase
{
    private readonly TestDbContext _dbContext;

    // This constructor uses dependency injection.
    public MyController(TestDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<ActionResult<int>> GetIceCreamCount()
    {
        var iceCreams = _dbContext.IceCreams.ToListAsync();
        return iceCreams.Count;
    }
}

You would also need to make sure, that you run the application for the processor architecture of the underlying database provider, which is likely to be 32 Bit for the usual Jet database driver.

To accomplish that in Visual Studio, you would need to make sure, that VS uses the correct version of dotnet, which can be done by adding the following lines to you project file (or something similar):

<PropertyGroup>
  <RunCommand Condition="'$(PlatformTarget)' == 'x86'">$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand>
  <RunCommand Condition="'$(PlatformTarget)' == 'x64'">$(ProgramW6432)\dotnet\dotnet</RunCommand>
</PropertyGroup>

Then set you platform target to x86 (either in the project file or in the project properties dialog).

The following program shows, how this would work (here without a controller):

Proof of Concept Application ```c# using System; using System.Diagnostics; using System.Linq; using System.Text; using EntityFrameworkCore.Jet; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace EfCoreJetSample { public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup(); } public class IceCream { public int IceCreamId { get; set; } public string Name { get; set; } } public class TestDbContext : DbContext { public DbSet IceCreams { get; set; } public TestDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { entity.HasKey(e => e.IceCreamId); entity.HasData( new IceCream {IceCreamId = 1, Name = "Vanilla"}, new IceCream {IceCreamId = 2, Name = "Chocolate"}, new IceCream {IceCreamId = 3, Name = "Strawberry"} ); }); } } public class Startup { public Startup(IConfiguration configuration) { Debug.Assert(!Environment.Is64BitProcess); Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddDbContext(options => options.UseJet("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=test.mdb;")); services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.Run(async httpContext => { using (var scope = app.ApplicationServices.CreateScope()) { var dbContext = scope.ServiceProvider.GetService(); dbContext.Database.EnsureDeleted(); dbContext.Database.EnsureCreated(); var iceCreams = dbContext.IceCreams .OrderBy(i => i.IceCreamId) .ToList(); Debug.Assert(iceCreams.Count == 3); Debug.Assert(iceCreams[0].Name == "Vanilla"); await httpContext.Response.WriteAsync( new StringBuilder() .AppendJoin("\r\n", iceCreams.Select(i => $"{i.Name} ({i.IceCreamId})")) .ToString()); } }); } } } ```

In theory, this should all work.


I want to use efcore.jet 2.2.0 in my asp.netcore 2.2.0 project.

Unfortunately, the provider does not yet work with the .NET Core (or ASP.NET Core) runtime, mainly because it depends on System.Data.OleDb from .NET Framework 4.

This is also stated on the main page of this repository:

This provider [...] does not work under the .NET Core runtime (netcore and netstandard).

Because of that, the provided sample code should not work with the .NET Core runtime at all.


The planned support for EF Core 3.1.0 will make use of the new System.Data.OleDb .NET Core package and will fully work with .NET Core 3.1.

Weijee commented 4 years ago

@bubibubi @lauxjpn Thank you for your explain。For now i am using System.Data.OleDb .NET Core package to access my MS Access.mdb, is there any release schedule of the JetEFCore3.1 now?

lauxjpn commented 4 years ago

I plan to start working on the upgrade in February.

See #34 for further details.

Weijee commented 4 years ago

I plan to start working on the upgrade in February.

See #34 for further details.

Thank you for your reply. Looking forward.