我正在.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文件引发以下异常:
因此,我无法理解我的类注册是否错误,或者连接字符串是否错误,或者两者都不是。 我还没有找到解决方案。任何帮助将不胜感激。