如何在方法中传递多个lambda表达式

时间:2017-07-11 23:27:42

标签: c# entity-framework generics lambda

假设我有一个通用数据访问层方法,用于使用类似代码更新记录:

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方法,因为有时我需要排除多个列,但我的方法不支持多列机制。

任何人都可以帮我解决这个问题吗?

4 个答案:

答案 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";
});

虽然这可能不是这个问题的直接答案,但我相信这是有用的并且会有所帮助。