简体   繁体   English

在 Entity Framework Core 中使用 2 个数据库共享一个 model

[英]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.

相关问题 Entity Framework Core 在数据库之间共享数据 - Entity Framework Core sharing data between databases 使用Entity Framework Core共享表 - Sharing a table using Entity Framework Core 实体框架核心-一种用于多个查询的模型 - Entity Framework Core - one model for multiple queries 如何将同一实体映射到不同的数据库并仅忽略 Entity Framework Core 中的一个数据库的列? - How to map same entity to different databases and ignoring a column only for one DB in Entity Framework Core? 在Entity Framework 6中使用不同的数据库 - Using different databases with Entity Framework 6 将Entity Framework与Archive数据库一起使用 - Using Entity Framework with Archive databases 在 .NET 中为 2 个数据库使用实体框架 - Using Entity Framework for 2 databases in .NET Entity Framework Core 没有在我的数据库中创建表 - Entity Framework Core is not creating tables in my databases Entity Framework Core 如何在不使用 Include().ThenInclude() 的情况下从模型中从多对多列出一对多 - Entity Framework Core how to list one to many from many to many from a model without using Include().ThenInclude() 具有2个数据库的Entity Framework Core(aspnetboilerplate webapp) - Entity Framework Core with 2 databases ( aspnetboilerplate webapp )
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM