在MVC中EF更新指定字段数据的有关问题

在MVC中EF更新指定字段数据的问题
本帖最后由 CrazyCode1981 于 2015-03-15 17:45:43 编辑
在开发中遇到一个问题 ,一直没有什么好的解决办法,在MVC中用户修改数据后,通过POST将数据返回后台Action接收,接收参数是EF实体模型,这时如果直接提交的话就会修改EF实体中的所有字段,但是用户在修改数据的时候并不是修改所有的数据。

想过一个比较笨的解决办法,先建一个用户实体,只有需要修改的字段、属性并且和EF的实体属性名称是一样的,用户提交后在Action接收,取出里面的ID到数据库中查询一次,获取到没有修改的数据的EF实体,然后通过反射的方式将里面的相同字段做对比,如果不同,就将字段名称记录到List集合

public T ModelConvertToEntity<T>(object OldViewModel, T DataEFModel, List<string> PIlist) where T : class,new()
        {
            Type OldModelType = OldViewModel.GetType();
            var OldModePropertys = OldModelType.GetProperties().Where(p => p.PropertyType.IsPublic == true).ToList();//获取属性集合

            Assembly T_Ass = Assembly.GetAssembly(typeof(T));
            object T_obj = T_Ass.CreateInstance(string.Join(".", new string[] { typeof(T).Namespace, typeof(T).Name }));//创建对象
            var T_objProPertys = T_obj.GetType().GetProperties().Where(p => p.PropertyType.IsPublic == true).ToList();//获取属性集合

            var DataEFModelProPertys = DataEFModel.GetType().GetProperties().Where(p => p.PropertyType.IsPublic == true).ToList();

            foreach (PropertyInfo oldPI in OldModePropertys)
            {
                var NewPI = T_objProPertys.Where(u => u.Name == oldPI.Name).Single();
                var DBPI = DataEFModelProPertys.Where(u => u.Name == oldPI.Name).Single();
                if (NewPI != null && DBPI != null)
                {
                    
                    object DBView = DBPI.GetValue(DataEFModel);//数据库中的值
                    object ViewValue = oldPI.GetValue(OldViewModel);//视图模型的值
                    if (ViewValue != DBView) //不想等 意味着做了修改 需要记录字段属性的名称 用户修改时 的IsModify
                    {
                        NewPI.SetValue(T_obj, ViewValue);//将视图模型的值赋给新的实体对象
                        PIlist.Add(oldPI.Name);//记录需要修改的字段
                    }

                }
            }
            return T_obj as T;
        }

但这个方法有个问题,就是比对  ViewValue != DBView 两个都是object类型的,必须要强转成相对应的类型对比值才有意义,这样我只能通过PropertyType.Name获取类型的名称,

switch(name)
{
case "String":
return A.ToString().Equals(B.ToString());
 
case "Int32" :
return (int)A==(int)B
.............
}

请问有没有更好的办法 在EF更新数据时 判断用户修改的数据 然后只更新这部分数据的方法? 罗里吧嗦的说了一大堆,表达能力有限,希望能明白我写的问题。

------解决思路----------------------
两个观点:
1. 不要滥用反射。一个应用程序中只有在极个别的工厂方法里才会用到反射。

2. 不要画蛇添足去搞什么“修改”。如果你觉的这个Model设计的不好,那么就设计其它的Model,通过其它的BLL接口方法去修改数据。一个数据库表对应4、5个不同的Model,对应8、9个不同的BLL方法,这是很平常的。在不同的BLL中,你自然就会编程分别修改同一个数据库表的不同字段(比如说,把“设置用户基本资料”跟“设置用户个人头像”作为两个独立的BLL功能提供给前端)。不用什么反射。