.NET Entity Framework:使用实际对象在上下文内查找代理
解决方案:WCF传输实体后在接收端上下文查找对应代理
我之前在项目里处理过几乎一模一样的场景,分享下我的实操思路和方法:
首先得明确几个前提:我们通常不会直接传输EF的动态代理对象(因为序列化容易出问题),一般是先把代理转成纯POCO实体再通过WCF发送;接收端拿到POCO后,要在自己的EF上下文里找是否已有对应主键的代理对象,核心是靠主键匹配来定位。
具体实现步骤
第一步:确保WCF传输的是POCO实体
从发送端上下文拿到代理对象后,先转成POCO:// 假设你的实体是Order,dbContext是发送端的EF上下文 var proxyOrder = dbContext.Orders.First(o => o.Id == orderId); // 转成POCO var pocoOrder = dbContext.Entry(proxyOrder).CurrentValues.ToObject() as Order;然后把
pocoOrder通过WCF发送,避免代理序列化的兼容性问题。第二步:接收端查找已有代理
拿到POCO实体后,有两种方式查找上下文里的代理:- 优先查本地缓存+自动查库:用Find()方法
Find()会先检查上下文的本地跟踪缓存(也就是已经加载的代理对象),找到直接返回;找不到就去数据库查询并加载:var receivedPocoOrder = ...; // 从WCF接收的POCO var existingProxy = dbContext.Orders.Find(receivedPocoOrder.Id); - 只查本地缓存:用Local属性
如果不想触发数据库查询,只检查已经加载到上下文内存里的实体:var existingProxy = dbContext.Orders.Local.FirstOrDefault(o => o.Id == receivedPocoOrder.Id);
- 优先查本地缓存+自动查库:用Find()方法
第三步:把接收的POCO转为代理(如果需要)
如果查不到现有代理,想把接收的POCO附加到上下文并生成代理,只需要:dbContext.Orders.Attach(receivedPocoOrder); // 或者指定状态 dbContext.Entry(receivedPocoOrder).State = EntityState.Unchanged;只要你的上下文开启了代理创建(默认是开启的,即
dbContext.Configuration.ProxyCreationEnabled = true),EF会自动为这个POCO生成代理对象。
注意事项
- 如果你非要直接传输代理对象,需要把WCF的序列化器换成
NetDataContractSerializer(默认的DataContractSerializer不支持动态生成的代理类型),但这种方式容易有版本兼容问题,不推荐。 - 一定要确保发送端和接收端的实体类定义完全一致(包括命名空间、属性、主键配置),否则会出现类型不匹配或者主键识别错误的问题。
内容的提问来源于stack exchange,提问作者PigSpider
相关产品推荐
相关产品推荐

