假设我有一个通用数据访问层方法,用于使用类似代码更新记录:
public virtual void Update<P>(Expression<Func<T, P>> excludeColumn, params T[] items)
{
foreach (T item in items)
{
_entities.Entry(item).State = EntityState.Modified;
_entities.Entry(item).Property(excludeColumn).IsModified = false;
}
_entities.SaveChanges();
}
这里我正在使用excludeColumn
param从更新中排除列,我将值传递给此参数
_companyProfileRepository.Update(x => x.EmailAddress, records);
x => x.EmailAddress
是一个表达式,我将其传递给通用Update
方法。我的问题是我想将多个列传递给Update
方法,因为有时我需要排除多个列,但我的方法不支持多列机制。
任何人都可以帮我解决这个问题吗?
答案 0 :(得分:0)
对于多列情况,您可以添加一个接受未修改列名称的重载。类似的东西:
public virtual void Update<TEntity>(IEnumerable<string> excludeColumnNames, params TEntity[] items)
{
foreach (var item in items)
{
_entities.Entry(item).State = EntityState.Modified;
foreach (var cn in excludeColumnNames)
{
_entities.Entry(item).Property(cn).IsModified = false;
}
}
_entities.SaveChanges();
}
答案 1 :(得分:0)
使用存储库模式,您可以将EF数据层包装在实际具有意义的内容中,而不是隐藏意图的通用/抽象代码。 一般来说,Repository Pattern的网络上有大量的例子,但我认为这是一种反模式,and I'm not alone。
e.g。 UserProfileRepository可以有这样的界面:
public interface IUserProfileRepository
{
void UpdateUserProfile(IUserProfile p);
}
这是一种对任何阅读代码的人都有意义的抽象,因为它使其意图明确。此外,上述代码更改的唯一原因是,如果实际上存储IUserProfile的方式发生了变化,并且在更新UserProfile时需要进行一些特殊处理,那么您可以在某处进行更改。
比较你的:
void Update<TEntity>(IEnumerable<string> excludeColumnNames, params TEntity[] items)
当你在代码周围调用这个方法以实现许多不同的结果时,这会模糊意义,如果有更新特定实体类型的特殊处理,你无处可去,所以它最终会被推到一层并在每次需要时重复。
还要考虑获取实体并更新它是两个非常不同的操作。您可能获得实体上的所有属性,但只更新其中的一些属性,我相信您在问题中指的是这些属性。我认为EF使读取和写入实体的感觉的方式几乎相同,是一种可怕的抽象,导致了大量的痛苦和痛苦。读取和写入数据是非常不同的用例,正如CQRS pattern所证明的那样。
答案 2 :(得分:0)
如果要传入多个列,请将它们传递给...
数组或列表是常用的方法。
public virtual void Update<P>(List<Expression<Func<T, P>>> excludeColumns, params T[] items)
{
foreach (T item in items)
{
foreach (Expression<Func<T, P>> excludeColumn in excludeColumns)
{
_entities.Entry(item).State = EntityState.Modified;
_entities.Entry(item).Property(excludeColumn).IsModified = false;
}
}
_entities.SaveChanges();
}
只要每列具有相同的类型P,那就没问题。
答案 3 :(得分:-1)
我有一个类似的方法,但使用linq-to-sql。这有点不同,但效果很好。您可能需要调整它以与EF一起使用。
public class Data
{
public static void Update<T>(Func<T, bool> where, Action<T> change)
{
IEnumerable<T> items = ((IEnumerable<T>)myDataContext.GetTable(typeof(T))).Where(where);
foreach (T item in items)
{
change(item);
}
myDataContext.SubmitChanges();
}
}
我这样用:
Data.Update<User>(u => u.Id == 3, u =>
{
u.Name = "John";
u.Age = 25;
u.Email = "john@email.com";
});
虽然这可能不是这个问题的直接答案,但我相信这是有用的并且会有所帮助。