繁体   English   中英

参考另一个上下文中的实体创建新实体

[英]Creating a new entity with reference to an entity from another context

我有2个projetcs PRJ1PRJ2 ,它们使用自己的数据库DB1DB2 这些数据库中的每一个都使用EF Code First Migration。

  • PRJ1用于管理产品库存(自4年以来已存在)。
  • PRJ2用于订单(全新项目仍在开发中)

现在我们来谈谈第二个项目。 在我的项目PRJ2中,我需要从其他数据库DB1访问数据。 所以我需要下订单产品。

以下是我到目前为止PRJ2的内容。请注意,我定义了两种不同的上下文。

// Context for accessing entities in DB1
public class DB1Context : DbContext
{
    static DB1Context()
    {
        Database.SetInitializer<DB1Context>(null);
    }
    public DbSet<Product> Products { get; set; }
}

// Context for accessing entities in DB2
public class DB2Context : DbContext
{
    static DB2Context()
    {
        Database.SetInitializer(new MigrateDatabaseToLatestVersion<DB2Context, DAL.Migrations.Configuration>());
    }
    public DbSet<Anything> Anythings { get; set; }
    public DbSet<Order> Orders { get; set; }
}

什么有效 :我可以从DB1Context(Products)或DB2Context(Anythings)查询数据。

什么不起作用 :创建我的订单实体。

// My Orders entity
public class Orders
{
    public int Id { get; set; }
    public int ProductId { get; set; }
    public int Quantity { get; set; }

    public virtual Product Product { get; set; }
}

位于DB2Context中的此实体引用Product实体,该实体是DB1Context的一部分。

现在的问题是,只要我在我的上下文DbSet<Order>添加此实体,我DbSet<Order>看到有一个等待Product的迁移。 此迁移用于在DB2Context中创建Product。 那不是我想要的。 此实体已存在于DB1Context中。 我似乎无法创建这个从其他上下文引用Product的Order实体。

你能证实这一点吗? 我错过了什么吗? 否则什么是最好的选择?

我认为你不能使用Entity Framework做到这一点。

该问题看起来像No-SQL数据库的问题。 当您拥有多个数据库时,您必须控制所有数据库的所有CRUD。 ADO无法为您执行此操作,因为您没有数据完整性。

一种可能的解决方案是将CRUD放在业务逻辑层中......或类似的东西。

假设您有一个OrderBll来控制:

public class OrderBll
{
    private DB1Context _DB1Context = new DB1Context();
    private DB2Context _DB2Context = new DB2Context();

    public List<Orders> GetOrders()
    {
        var orders = _DB2Context.Orders.Where(???).ToList();
        var productIds = orders.Select(x => x.ProductId).Distinct().ToArray();
        var products = _DB1Context.Products.Where(x => productIds.Contains(x.Id)).ToList(); // Optimize the load of all products in orders

        // Set the product object in the order list
        foreach( var order in orders )
        {
             order.Product = products.FirstOrDefault(x=>x.Id == order.ProductId);
        }
        return orders;
    }
}

请记住,您必须在“ Ignore Orders映射“ Product属性。

因此,您必须自己设置外键并执行所有约束检查。

但是,如果其他人有更好的解决方案,我会很高兴知道。

理想情况下,这是你应该瞄准的目标。

  1. 将订单和产品放在同一个数据库中。 然后,您就可以在订单和产品之间创建关系。 您最终会得到一个EF上下文,这将为您提供可靠的解决方案。

如果由于某种原因您不能将订单放在与产品相同的数据库中,那么解决方案仍然有其自身的局限性。

  1. 例如,您可以将products表从DB1复制到DB2,每分钟运行一次复制。 您可以编写自己的复制组件或使用数据库的复制功能。 如果可以在DB2中删除产品,则复制可能会删除DB1中的产品和订单,或者仅标记已删除的产品。 由你来决定。 如果PRJ2可以更新产品表,那么复制必须是双向的。 这变得更复杂。 此解决方案的EF上下文将包含从订单到产品,从产品到订单的关系。

  2. 另一种解决方案是在DB1中保留一个“代理”产品表,其中包含订单中引用的产品的ID。 在您的业务逻辑中,您决定是否需要从DB1访问实际的产品表。 例如,在创建新订单时,您将从DB1访问产品,并在代理表中插入其ID(如果不存在)。 在显示订单的产品时,您首先要从DB1中检索订单的产品ID,然后从DB1中检索它们的完整描述。 更新产品库存时,作为创建订单的一部分,您可以访问DB1,可能使用跨越DB的事务! 和DB2。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM