Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 参照另一上下文中的实体创建新实体_Entity Framework_Entity Framework Migrations - Fatal编程技术网

Entity framework 参照另一上下文中的实体创建新实体

Entity framework 参照另一上下文中的实体创建新实体,entity-framework,entity-framework-migrations,Entity Framework,Entity Framework Migrations,我有两个项目PRJ1和PRJ2,它们使用自己的数据库DB1和DB2。每个数据库都使用EF代码优先迁移 PRJ1用于管理产品库存(已存在4年) PRJ2用于订单(全新项目仍在开发中) 现在我们只谈第二个项目。在我的项目中,我需要访问另一个数据库中的数据。所以我需要订购产品 以下是我到目前为止为PRJ2 注意,我定义了两个不同的上下文 // Context for accessing entities in DB1 public class DB1Context : DbContext {

我有两个项目PRJ1PRJ2,它们使用自己的数据库DB1DB2。每个数据库都使用EF代码优先迁移

  • PRJ1用于管理产品库存(已存在4年)
  • PRJ2用于订单(全新项目仍在开发中)
现在我们只谈第二个项目。在我的项目中,我需要访问另一个数据库中的数据。所以我需要订购产品

以下是我到目前为止为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; }
}
位于DB2Context中的该实体引用的是属于DB2Context的
产品
实体

现在的问题是,只要我将这个实体添加到我的上下文
DbSet
中,我就会看到有一个迁移正在等待产品。此迁移用于在我的DB2Context中创建产品。那不是我想要的。此实体已存在于DB1Context中。似乎我无法创建这个订单实体,它从其他上下文引用产品


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

我认为使用实体框架无法做到这一点

这个问题看起来像是无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;
    }
}
公共类OrderBll
{
私有DB1Context_DB1Context=新的DB1Context();
私有DB2Context_DB2Context=new DB2Context();
公共列表GetOrders()
{
var orders=_DB2Context.orders.Where(???).ToList();
var ProductId=orders.Select(x=>x.ProductId.Distinct().ToArray();
var products=_DB1Context.products.Where(x=>productIds.Contains(x.Id)).ToList();//优化订单中所有产品的负载
//在订单列表中设置产品对象
foreach(订单中的var订单)
{
order.Product=products.FirstOrDefault(x=>x.Id==order.ProductId);
}
退货订单;
}
}
请记住,您必须在
订单
中映射
产品
属性,如
忽略

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


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

理想情况下,这就是你应该追求的目标

  • 将订单和产品放在同一数据库中。然后,您将能够在订单和产品之间创建关系。您将得到一个单一的EF上下文,这将为您提供一个可靠的解决方案
  • 如果出于任何原因,您不能将订单与产品放在同一数据库中,那么解决方案仍有其自身的局限性

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

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


  • 是的,我可以证实。不,你没有错过任何东西。选择?有时,这可以通过将表链接到另一个数据库来解决,但这是一个脆弱的解决方案。你仍然会有迁移问题。谢谢@GertArnold的评论。我很失望,我的问题似乎没有解决办法。我一定不是第一个遇到这种情况的人。我所介绍的场景在我看来相当经典。在另一个数据库中拥有实体的导航属性一点也不经典。当然,各种数据源之间的通信是例行的,但这并不相同。通常,这是通过API(即web服务)实现的,而不是通过直接连接到多个数据库来实现的。但是,通过使用API,我们无法实现关系完整性。在我的例子中,我可以使用一个web服务从我的DB1中检索所有产品,只需在DB2中使用一个
    int
    ,以保持对特定产品(DB1)的简单“引用”。但是这个产品可以在没有任何关系完整性约束的情况下被删除(在DB1中)。您也不能跨数据库强制执行引用完整性。至少,不受外键限制。非常有趣,谢谢。让我们看看其他人是否有其他想法/选择。
    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;
        }
    }