[英]Using 2 databases sharing one model in Entity Framework Core
I have 2 databases, one on-premises and one in the cloud, I want them to be in sync whenever the local database adds or updates data.我有 2 个数据库,一个在本地,一个在云中,我希望它们在本地数据库添加或更新数据时保持同步。
I created the 2 databases and both of them share the same model ( School
)我创建了 2 个数据库,它们都共享相同的 model(
School
)
public virtual DbSet<School> School { get; set; }
The problem that happens is, when I do:发生的问题是,当我这样做时:
TestDb1DbContext context;
SecondProjectDb remoteContext;
string connString = ConfigurationManager.ConnectionStrings["TestDb1"].ConnectionString;
var contextOptions = new DbContextOptionsBuilder<TestDb1DbContext>().UseSqlServer(connString).Options;
context = new TestDb1DbContext(contextOptions);
string remoteconnString = ConfigurationManager.ConnectionStrings["RemoteTestDb1"].ConnectionString;
var remotecontextOptions = new DbContextOptionsBuilder<SecondProjectDb>().UseSqlServer(connString).Options;
remoteContext = new SecondProjectDb(remotecontextOptions);
var schools = remoteContext.School.ToList();
I get the results of context
database, while the remoteContext
is empty because I have not added anything there.我得到了
context
数据库的结果,而remoteContext
是空的,因为我没有在那里添加任何东西。
If I try to add a row如果我尝试添加一行
school.Id = "one";
school.Name = "myschool";
context.School.Add(school);
remoteContext.School.Add(school);
context.SaveChanges();
>>> remoteContext.SaveChanges();
I get errors of duplicate Ids.我收到重复 ID 的错误。
I am not sure how to keep these 2 databases in sync, since it seems that both contexts are sharing the same reference?我不确定如何使这两个数据库保持同步,因为两个上下文似乎共享相同的引用?
So you have a remote database, which is fairly standard.所以你有一个远程数据库,这是相当标准的。 It can be changed using the standard entity framework methods.
可以使用标准实体框架方法对其进行更改。
You also have a local database, which is very similar to the remote database, except, that when it is to be updated, it also has to update the remote database.您还有一个本地数据库,它与远程数据库非常相似,只是当它要更新时,它还必须更新远程数据库。
You've learned, that if you have a class that behaves almost exactly like another class, except for a few aberrations, you should at least consider the possibility of derivation.您已经了解到,如果您有一个 class 的行为几乎与另一个 class 完全相同,除了一些异常,您至少应该考虑推导的可能性。
I want them to be in sync whenever the local database adds or updates data.
每当本地数据库添加或更新数据时,我希望它们保持同步。
Apparently, if the remote database changes, the local database doesn't have to be updated to reflect those changes.显然,如果远程数据库发生更改,则不必更新本地数据库以反映这些更改。
How about this:这个怎么样:
// your current DbContext, can handle your local database as well as your remote one
// however, if the local database is updated, this version doesn't update the remote one.
class MyDbContext : DbContext
{
public MyDbContext(...) : DbContext(...) {...}
public DbSet<School> Schools {get; set;}
public DbSet<...> ... // etc
}
I don't know the parameters of your constructor, let's assume they are:我不知道你的构造函数的参数,让我们假设它们是:
public MyDbContext(MyDbContextParameters parameters) ...
We create a derived class that represents your local database.我们创建一个派生的 class 代表您的本地数据库。 To make it more generic: it represent a database, that whenever it is updated, it will also update another database (in your case: the remote database).
为了使其更通用:它代表一个数据库,每当它更新时,它也会更新另一个数据库(在您的情况下:远程数据库)。
The constructor of this class, needs the parameters to create the local database, and the ones to create the remote database.这个 class 的构造函数,需要创建本地数据库的参数,以及创建远程数据库的参数。
class MyAutoUpdateDbContext : MyDbContext // TODO: invent a proper name
{
private MyDbContextParameters RemoteParameters {get; set;}
public MyAutoUpdateDbContext(
MyDbContextParameters localParameters,
MyDbContextParameters remoteParameters) :
MyDbContext(localParameters)
{
this.RemoteParameters = remoteParameters;
}
The deviation of a standard MyDbContext is when you call SaveChanges.标准 MyDbContext 的偏差是在您调用 SaveChanges 时。 Instead of only updating the local database, you need to update the remote database as well.
您不仅需要更新本地数据库,还需要更新远程数据库。 Continuing MyAutoUpdateDbContext:
继续 MyAutoUpdateDbContext:
public override int SaveChanges ()
{
// TODO: detect which items are about to be updated
// update them in the remote database before calling base.SaveChanges
this.SaveChangesInRemote();
return this.SaveChanges();
}
There might be a problem, if some items can't be updated.如果某些项目无法更新,则可能存在问题。 If you need to handle this scenario, consider to use a transaction before updating the databases.
如果您需要处理这种情况,请考虑在更新数据库之前使用事务。 This is a bit out-of-scope of the question, so I'll ignore it.
这有点超出问题的范围,所以我会忽略它。
To save the changes in Remote, you'll need to find out which items will be saved in the local database when you call this.SaveChanges()
.要在 Remote 中保存更改,您需要在调用
this.SaveChanges()
时找出哪些项目将保存在本地数据库中。 You can find these items in this.ChangeTracker
.您可以在
this.ChangeTracker
中找到这些项目。
private int SaveChangesInRemote()
{
var changeTracker = this.ChangeTracker;
if (changeTracker.HasChanges)
{
IEnumerable<DbEntityEntry> changedEntries = this.changeTracker.Entries
.Where(entry => entry.State != EntityState.Unchanged);
return this.SaveInRemote(changedEntries);
}
}
To save the changed entries in remote database, create the DbContext for the remote database and Attach all changed entries before calling SaveChanges:要将更改的条目保存在远程数据库中,请为远程数据库创建 DbContext 并在调用 SaveChanges 之前附加所有更改的条目:
private int SaveInRemote(IEnumerable<DbEntityEntry> changedEntries)
{
using (MyDbContext remoteDbContext = this.CreateRemoteDbContext())
{
foreach (DbEntityEntry entry in changedEntries)
{
remoteDbContext.Attach(entry);
}
return remoteDbContext.SaveChanges();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.