首页 新闻 会员 周边

EF+WCF怎样更新数据?

0
悬赏园豆:10 [待解决问题]

以常见的权限关系来说,User\Role 2个实体是多对多关系,其POCO类似:

View Code
    [DataContract]
public class User
{
public User()
{
this.Id = Guid.NewGuid();
this.Roles = new List<Role>();
}

[Key]
[DataMember]
public Guid Id
{
get;
private set;
}

[DataMember]
public string UserName{get;set;}
[DataMember]
public string PassWord{get;set;}

[DataMember]
public virtual List<Role> Roles{get;set;}
}


创建服务类似: 

ServiceResult  UpdateUser(User user);

这时候,我们知道,如果WCF与EF结合使用,有一些注意点:一,WCF传递的需要是POCO类,且不能循环引用(这一点通过在实体类添加[DataContract(IsReference=true)]即可),

二一个问题是EF的延迟加载和代理实例机制,导致EF查询结果并非POCO类,而是代理类,所以需要关系EF代理实例模式:Configuration.ProxyCreationEnabled = false;

 

现在问题来啦,如何实现UpdateUser方法呢,一般我们会用IDbSet.Attach()方法来更新,代码如:

 m_DbSet.Attach(entity);
this.DbContext.Entry<T>(entity).State = EntityState.Modified;
this.DbContext.SaveChanges();

但是这时候你就会发现,由于EF为了支持WCF服务已经关闭了ProxyCreationEnabled ,所以无论如何,这里的Attach方法是不能执行成功的,

那这时候你会想,那我不采用Attach方法,先Delete实体,再重新添加行不行呢,

 

NO  no  no ,由于EF在SaveChanges的时候会根据实体关系,自动修改数据表,所以当你删除User时候的时候会删除User表以及User_Role表中的记录,此时再添加User实体的话,会向User表添加User,User_Role表添加关系,Role表添加Role(因为User.Roles的存在),

这时候你会发现Role表添加Role就不行了,因为记录已经存在了;所以这种方式也不能很好的解决问题!!

怎么办呢,我暂时也不知道怎么办,所以来此求助各位大牛~~看看有什么经验,好的处理方法!

ps:Data Services、Ria services暂时不考虑,因为我的应用需要对具体的操作进行授权!非Web系统!

lianghugg的主页 lianghugg | 初学一级 | 园豆:180
提问于:2011-11-21 08:54
< >
分享
所有回答(3)
0

这个弄的太复杂了吧,你如果用wcf那么调用wcf后就与调用方没什么关系了,数据库操作就在写在WCF服务端啊

乱世文章 | 园豆:147 (初学一级) | 2011-11-21 09:36

呵呵。,主要是为了方便, 不想一个实体也N个对应修改属性的服务!

直接通过修改实体,提交更新,是最好最直接的办法,  这其中关键就是要控制好服务端与客户端 的实体状态一致性,和POCO完整性;这可能也是后来Data Services 和 Ria Services 推出的原因之一吧!

支持(0) 反对(0) lianghugg | 园豆:180 (初学一级) | 2011-11-21 12:12
2

问题已经得到解决了,稍后我会写详细的设计方式到博客;

现在简单说下 关于更新这一问题的解决方式:

Model First方式请参照:

http://blogs.msdn.com/b/cesardelatorre/archive/2008/09/04/updating-data-using-entity-framework-in-n-tier-and-n-layer-applications-short-lived-ef-contexts.aspx

 

Code-First方式需要如下操作:

        public virtual void Update(T entity)
{
T current = this.Where(m => m.Id.Equals(entity.Id))
.SingleOrDefault();
if (current != null)
{
var context = ((IObjectContextAdapter)DbContext).ObjectContext;
ObjectStateEntry objectStateEntry;
if (context.ObjectStateManager.TryGetObjectStateEntry(current, out objectStateEntry))
{
objectStateEntry.ApplyCurrentValues(entity);
objectStateEntry.SetModified();
this.Commit();
}
}
}

注意,在Code First这种方式中,如果实体包含外键关系,可能无关更新关系属性, 所以要求增加相应的服务用于操作外键关系属性, 具体原因稍后我在分析下!

lianghugg | 园豆:180 (初学一级) | 2011-11-21 12:15

T current = this.Where(m => m.Id.Equals(entity.Id))
                     .SingleOrDefault();

请问this指的是什么? 这条语句好像检索不出T current啊?

支持(0) 反对(0) Greatcqi | 园豆:175 (初学一级) | 2014-09-27 23:48
0

用EmitMapper怎么样?

public virtual void Update(TEntity entityToUpdate)

{

      var entry = context.Entry(entityToUpdate);

      if (entry.State == EntityState.Detached)

      {

          var entityOrigin = GetByID(entityToUpdate.ID);

          EmitMapper.ObjectMapperManager

               .DefaultInstance.GetMapper<TEntity, TEntity>()

               .Map(entityToUpdate, entityOrigin);

       }

}

阳春sin | 园豆:202 (菜鸟二级) | 2011-12-21 23:42
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册