c# - C# Entity Framework 在同一个数据库中创建两个 DbContext´s
问题描述
我有一个包含上下文的通用 DbContext,当我想在 DB 中保存模型时,我想创建此类的实例并保存对象。在测试中,我断言,第一个 Object 已正确保存,但第二个对象确实抛出异常"No such Table"
。为了明确这一点,如果我使用之前未创建的其他模型调用我的控制器,它确实会引发此异常。下面的测试表明了这一点。当我查看实际创建的数据库时,其中只有一个表。
有人可以告诉我有什么问题吗?
这是我的 DbContext:
public class DbEntryController<TEntity> : DbContext
where TEntity : class
{
protected static NLog.Logger Log = LogManager.GetCurrentClassLogger();
private static object _locker = new();
public DbSet<TEntity> Context { get; set; }
private string _tableName;
public DbEntryController(string tableName, DbContextOptions<DbEntryController<TEntity>> options)
: base(options)
{
_tableName = tableName;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TEntity>().ToTable(_tableName, schema: typeof(TEntity).Name);
}
public override int SaveChanges()
{
var entries = ChangeTracker
.Entries()
.Where(e => e.Entity is BaseEntry
&& (e.State == EntityState.Added
|| e.State == EntityState.Modified));
foreach (var entityEntry in entries)
{
((BaseEntry)entityEntry.Entity).LastUpdate = DateTime.Now;
if (entityEntry.State == EntityState.Added)
{
((BaseEntry)entityEntry.Entity).CreationTime = DateTime.Now;
}
}
Database.EnsureCreated();
Database.Migrate();
return base.SaveChanges();
}
public bool TryAddReceived<T>(string content, T context)
where T : TEntity, IReceiveDbEntry
{
return this.Save(Direction.Received, content, context);
}
public bool TryAddSent<T>(string content, T context)
where T : TEntity, ISendDbEntry
{
return this.Save(Direction.Sent, content, context);
}
}
这是我创建它的实例的方法:
using var db = DbController.FromDBPath<DbEntryController<MyModel>>((options) => new DbEntryController<MyModel>(nameof(MyModel), options));
这里是 FromDBPath 方法:
public static TContext FromDBPath<TContext>(Func<DbContextOptions<TContext>, TContext> creator, string dbPath = null)
where TContext : DbContext
{
if (dbPath == null)
Log.Trace($"No DB Path given. Use: {dbPath = Configuration.Instance.SQLiteDbPath}");
var builder = new DbContextOptionsBuilder<TContext>();
try
{
Log.Trace("Try use sqlite");
builder.UseSqlite($"Data Source={Path.GetFullPath(dbPath)}");
Log.Trace("Try create EventLoggingContext");
var e = creator(builder.Options);
e.Database.EnsureCreated();
Log.Trace("DB Create success");
return e;
}
catch (Exception ex)
{
Log.Error("Could not create DB");
Log.Error(ex);
return creator(builder.Options);
}
}
我在 nunit 框架中编写的测试:
[Test]
public void InsertSoapRequest()
{
var sequence = new SequenceNumberDbEntry { Next = 2000000000 };
Assert.True(sequence.SuperFancyCreateXmlMethod(out var xml));
using (var db = (EventLoggingContext)DbController.FromDBPath<DbEntryController<Event>>((options) => new EventLoggingContext("InOut", options), dbPath))
{
Assert.True(db.TryAddEvent(xml, Direction.Received));
Assert.True(db.TryAddEvent(xml, Direction.Sent));
db.SaveChanges();
}
using (var db = DbController.FromDBPath<DbEntryController<MyModel>>((options) => new DbEntryController<MyModel>("SequenceNumbers", options), dbPath))
{
db.TryAddReceived(xml, sequence);
var max = db.SelectMaxTransaktionId();
Assert.AreEqual(2000000000, max);
}
}
例外:
最后但并非最不重要的是我的模型:
[Table("SequenceNumbers", Schema = nameof(MyModel))]
public class MyModel : BaseEntry, ISendDbEntry, IReceiveDbEntry
{
public uint Next { get; set; }
public uint Previos { get; set; }
public DateTime ReceiveTime { get; set; }
public DateTime SendTime { get; set; }
}
解决方案
推荐阅读
- android - Android:如何在来自 Firestore 的小部件中显示数据?
- time-complexity - 2个嵌套循环的时间复杂度
- python-3.x - 在引发前面的异常时捕获由“finally”引起的异常
- database - 是否有可以操作布尔值的数据库
- java - 测试时没有匹配的bean,但在服务器上完美运行
- php - Getting Column not found Error at Illuminate\Database\QueryException?
- docker - docker run 中的卷和 dockerfile 中的 COPY 的差异
- javascript - 有没有办法通过 Pixi.js 画一个环?
- rust - rust 中的“match ref”是什么意思?
- laravel - Laravel 安排推送通知并在必要时取消它