EntityframeworkCore.jet无法在4.8 .net项目中创建msaccess数据库

时间:2019-12-14 19:19:17

标签: ms-access entity-framework-core .net-4.8

我正在.net 4.8中创建一个应用程序,使用该应用程序我无法将一些记录从mysql数据库保存到可移植ms Access(.mdb)记录中。使用mdb的原因是因为它可以从程序中读取,该程序读取保存为blob(在mysql中)的某些类型的图表。 我想每次以编程方式创建一个.mdb文件,并使用不同的名称(基于日期时间)在用户首选项目录中。这也意味着动态连接字符串。

我决定使用EntityFrameworkCore.Jet包。

因此,我遵循了一个创建工厂和存储库类的示例(该实现是借用的,但是我丢失了链接……对不起)。所以我有 MsAccessContext类

public class MsAccessContext :DbContext
    {
        public MsAccessContext()
        {
        }

        public MsAccessContext(DbContextOptions<MsAccessContext> options)
            : base(options)
        {

        }

        public virtual DbSet<RadonDTOWithIsp> Radon { get; set; }
        public string defaultConnectionString = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Spectra_MsAccess_Databases\\Radon.mdb;";

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseJet(defaultConnectionString);
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<RadonDTOWithIsp>(entity =>
            {

                entity.ToTable("radon");
                entity.Property(e => e.Id)
                    .HasColumnName("id")
                    .HasColumnType("Long");
                entity.Property(e => e.Id).UseJetIdentityColumn();


                entity.Property(e => e.Location)
                   .IsRequired()
                   .HasColumnName("location")
                   .HasColumnType("TEXT");

                entity.Property(e => e.Counter).HasColumnType("INTEGER");

                entity.Property(e => e.Isp)
                    .HasColumnName("ISp")
                    .HasColumnType("Ole Object");

                entity.Property(e => e.DateM).HasColumnType("Date/Time");

                entity.Property(e => e.Device).HasColumnType("TEXT");

                entity.HasIndex(e => new { e.DateM, e.Location })
                   .HasName("DateLocation")
                   .IsUnique();

            });
        }
    }

MsAccessFactory类

 public class MsAccessFactory
    {
        public static Dictionary<string, string> ConnectionStrings { get; set; }

        public static void SetConnectionString(Dictionary<string, string> connStrs)
        {
            ConnectionStrings = connStrs;
        }

        public MsAccessContext CreateDbContext(string connectionString)
        {
            var optionsBuilder = new DbContextOptionsBuilder<MsAccessContext>();
            optionsBuilder.UseJet(connectionString);
            var context = new MsAccessContext(optionsBuilder.Options);            
            context.Database.EnsureCreated();
            return context;
        }

    }

和MsAccessRepository类

public class MsAccessRepository
    {
        protected MsAccessContext db;
        private readonly MsAccessFactory contextFactory;
        public MsAccessRepository(MsAccessFactory contextFactory)
        {
            this.contextFactory = contextFactory;
        }

        public MsAccessContext InitializeDatabaseContext(string connectionString)
        {
            db = contextFactory.CreateDbContext(connectionString);            
            return db;
        }
    }

像这样将它们注入Unity IoC

public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers

            // e.g. container.RegisterType<ITestService, TestService>();

            GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
            container.RegisterSingleton<MsAccessFactory>();
            container.RegisterSingleton<MsAccessRepository>();
            container.RegisterSingleton<MsAccessContext>();
        }
    }

我每次都通过Web api控制器使用它来创建带有动态连接字符串的新数据库。

[HttpPost]
        public async Task<IHttpActionResult> SaveToMdb(SendModel model)
        {
            string path = string.Format($"{model.path.Replace("/", "\\")}");
            //string fileName = $"Spectra-Isp-{DateTime.Now.ToString("ddmmyyyy HHmmss")}.mdb";
            string connectionString = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={path}";

            var msAccessDb = _msAccessRepo.InitializeDatabaseContext(connectionString);
            if(msAccessDb.Database.EnsureCreated())
                msAccessDb.Radon.AddRange(model.radonDTOWithIsps);
            await msAccessDb.SaveChangesAsync();            
            return Ok(model.radonDTOWithIsps);
        }

问题在于线路

if(msAccessDb.Database.EnsureCreated())

抛出一个异常,如邮递员所见 类型

{
    "Message": "An error has occurred.",
    "ExceptionMessage": "Cannot create database using the specified connection string.",
    "ExceptionType": "System.Exception",
    "StackTrace": "   at System.Data.Jet.AdoxWrapper.CreateEmptyDatabase(String connectionString)\r\n   
    at System.Data.Jet.JetStoreSchemaDefinition.JetStoreDatabaseHandling.TryDatabaseOperation(String commandText)\r\n   
    at System.Data.Jet.JetCommand.ExecuteNonQuery()\r\n   
    at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)\r\n   
    at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)\r\n   
    at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)\r\n   
    at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)\r\n   
    at EntityFrameworkCore.Jet.Storage.Internal.JetDatabaseCreator.Create()\r\n   
    at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureCreated()\r\n   
    at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated()\r\n   
    at MsAccessService.AccessDbContext.MsAccessFactory.CreateDbContext(String connectionString) 
    in D:\\GITPROJECTS\\MsAccessService\\MsAccessService\\AccessDbContext\\MsAccessFactory.cs:line 25\r\n   
    at MsAccessService.AccessDbContext.MsAccessRepository.InitializeDatabaseContext(String connectionString) 
    in D:\\GITPROJECTS\\MsAccessService\\MsAccessService\\AccessDbContext\\MsAccessRepository.cs:line 20\r\n   
    at MsAccessService.Controllers.ConvertionsController.<SaveToMdb>d__2.MoveNext() 
    in D:\\GITPROJECTS\\MsAccessService\\MsAccessService\\Controllers\\ConvertionsController.cs:line 30\r\n
    --- End of stack trace from previous location where exception was thrown ---\r\n   

    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   
    at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__1`1.MoveNext()\r\n
    --- End of stack trace from previous location where exception was thrown ---\r\n   

    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   
    at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()\r\n
    --- End of stack trace from previous location where exception was thrown ---\r\n   

    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   
    at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n
    --- End of stack trace from previous location where exception was thrown ---\r\n   

    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   
    at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()",
    "InnerException": {
        "Message": "An error has occurred.",
        "ExceptionMessage": "Class not registered",
        "ExceptionType": "System.Runtime.InteropServices.COMException",
        "StackTrace": "   at System.Dynamic.ComRuntimeHelpers.CheckThrowException(Int32 hresult, ExcepInfo& excepInfo, UInt32 argErr, String message)\r\n   at CallSite.Target(Closure , CallSite , ComObject , String )\r\n   at CallSite.Target(Closure , CallSite , Object , String )\r\n   at System.Data.Jet.AdoxWrapper.CreateEmptyDatabase(String connectionString)"
    }
}

在Visual Studio内部,UnityContainer.Resolution.cs文件引发以下异常:

Exception about InvalidRegistration inside Unity

因此,我无法理解我的类注册是否错误,或者连接字符串是否错误,或者两者都不是。 我还没有找到解决方案。任何帮助将不胜感激。

0 个答案:

没有答案