我有2个项目 PRJ1 和 PRJ2 ,它们使用自己的数据库 DB1 和 DB2 。每个数据库都使用EF代码优先迁移。
现在让我们仅讨论第二个项目。在我的项目 PRJ2 中,我需要访问其他数据库 DB1 中的数据。所以我需要订购产品。
这是到目前为止我获得的 PRJ2 请注意,我定义了2个不同的上下文。
// 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(产品)或DB2Context(任何内容)中查询数据。
尚无法解决的问题:创建我的订单实体。
// 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>
中添加该实体,我就会看到有一个迁移正在等待产品。此迁移用于在我的DB2Context中创建产品。那不是我想要的该实体已经存在于DB1Context中。看来我无法创建从其他上下文引用产品的这个Order实体。
您可以确认吗?我错过了什么吗?否则最好的选择是什么?
答案 0 :(得分:0)
我认为您无法使用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;
}
}
请记住,您必须像Product
一样在Orders
中映射Ignore
属性。
因此,您必须自己设置外键并进行所有约束检查。
但是,如果其他人有更好的解决方案,我将很高兴知道。
答案 1 :(得分:0)
理想情况下,这就是您的目标。
如果由于某种原因您无法在与产品相同的数据库中下订单,那么解决方案仍然有其自身的局限性。
您可以将product表从DB1复制到DB2,例如,复制每分钟运行一次。您可以编写自己的复制组件或使用数据库的复制功能。如果可以在DB2中删除产品,则复制可以删除DB1中的产品和订单,或者只是标记已删除的产品。由您决定。如果PRJ2可以更新产品表,则必须同时进行复制。这变得更加复杂。此解决方案的EF上下文将包含从订单到产品的关系,以及从产品到订单的关系。
另一个解决方案是在DB1中保留一个“代理”产品表,其中包含订单中引用的产品的ID。在业务逻辑中的任何地方,您都决定是否需要从DB1访问实际产品表。例如,当创建一个新订单时,您将访问DB1中的产品,如果没有,则将它们的ID插入代理表中。显示订单产品时,您首先要从DB1检索订单的产品ID,然后再从DB1检索其完整描述。在更新产品库存时,作为创建订单的一部分,您可能会使用跨DB的事务访问DB1!和DB2。