在MVC中EF更新指定字段数据的有关问题
在MVC中EF更新指定字段数据的问题
在开发中遇到一个问题 ,一直没有什么好的解决办法,在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功能提供给前端)。不用什么反射。
在开发中遇到一个问题 ,一直没有什么好的解决办法,在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功能提供给前端)。不用什么反射。