我正在使用具有Code First方法的Entity Framework 5,并使用Fluent API进行实体配置.我的项目有一个特定的产品实体,它从数据库中获得一半的数据,另一半从通过WCF客户端检索的数据合同(其用于管理产品库存的第三方系统)获取另一半.数据合同是Product Entity类的成员(尚未确定的属性或方法).
我更希望在实体中不包含任何WCF客户端逻辑.我更喜欢将这个逻辑保留在Repository代码(DbContext,DbSet等)中.
那么在从数据库中检索到产品实体之后,是否有一种技术来挂接Entity Framework(或拦截)?我应该注意,产品实体在其他实体上显示为导航属性.如果挂钩或拦截是可能的,那么这意味着我可以在EF从数据库加载产品实体之后立即从SOAP服务检索数据合同.我的项目的好处是WCF客户端检索代码不需要在整个应用程序中重复.
一个想法是实现数据合同的IDbSet,IDbSet将负责检索它.然后以某种方式欺骗EF考虑其在产品实体上的导航属性.但是我不知道数据库DbSet是否可以与同一个DbContext中的非数据库IDbSet混合.还有另一个问题 – EF如何从IDbSet植入中检索导航属性?在投入时间之前,我想知道这个想法是否可行.我也想知道从哪里开始寻找.
请注意,我一直在使用.NET十多年,但这个EF5的东西对我来说还是比较新的.
提前致谢.
萨姆
解决方法
今天我在实体框架中发现了一个似乎正在寻找的事件.
ObjectContext.ObjectMaterialized Event.显然,DbContext实现了IObjectContextAdapter,这反过来暴露了ObjectContext.从那里我可以订阅ObjectMaterialized事件.
MSDN Reads:
Occurs when a new entity object is created from data in the data
source as part of a query or load operation.
以下代码演示了我如何使用ObjectMaterialized事件来解决我的一个首选项有一个中心点来放置WCF客户端访问逻辑的问题.
// seperate assembly - does not use Domain.Repositories assembly namespace Domain.Models { // the data contract [DataContract] public class ProductInventoryState { [DataMember] public int StockStatus { get; set; } [DataMember] public IEnumerable<String> SerialNumbers { get; set; } // etc.... } // the entity public class Product { public Guid Key { get; set; } public string ProductCode { get; set; } public ProductInventoryState InventoryState { get; set; } // etc.... } } // seperate assembly - uses Domain.Models assembly namespace Domain.Repositories { public class MainRepository : DbContext { public MainRepository() { ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += ObjectContext_ObjectMaterialized; } protected void ObjectContext_ObjectMaterialized(object sender,ObjectMaterializedEventArgs e) { if (e.Entity == null) return; if (e.Entity is Product) { Product product = (Product)e.Entity; // retrieve ProductInventoryState from 3rd party SOAP API using (ThirdPartyInventorySystemClient client = new ThirdPartyInventorySystemClient()) { // use ProductCode to retrieve the data contract product.InventoryState = client.GetInventoryState(product.ProductCode); } } } } }