可以采用不同表格并对常用列进行操作的函数

时间:2014-10-03 15:30:25

标签: c# linq entity-framework

我有许多不同的表,每个表都有一些公共列和每个表独有的一些列。我使用实体框架来操作这些表,并使用LINQ查询进行过滤,排序等。下面的代码是我遇到的情况的一个高度简化的例子。

        var filter = "A";
        using (var dc = new MyDataEntities())
        {
            var rpt1 = dc.Table1.Where(x => x.Name.StartsWith(filter));
            var rpt2 = dc.Table2.Where(x => x.Name.StartsWith(filter));
            var rpt3 = dc.Table3.Where(x => x.Name.StartsWith(filter));
        }

如果我决定将过滤器从StartsWith更改为Contains,我必须在3个位置更改它。如果我决定要添加排序,我必须在3个位置添加它等等(因为你可以猜到我的实际代码在多个类中出现了这个逻辑,并且超过3个实例。)

有没有办法编写一个可以接受任何表并对该表中的公共列进行操作的函数?所以我的最终结果将是:

        using (var dc = new MyDataEntities())
        {
            var rpt1 = Filter(dc.Table1);
            var rpt2 = Filter(dc.Table2);
            var rpt3 = Filter(dc.Table3);
        }

这样我就可以将逻辑过滤到我的任何表上的Name列中的一个Filter()函数。想法?

1 个答案:

答案 0 :(得分:2)

让我定义所涉及的所有类:

public class Table1
{
    public string Name { get; set; }
}

public class Table2
{
    public string Name { get; set; }
}

public class Table3
{
    public string Name { get; set; }
}

你可以告诉POCO会更复杂但是对于这个例子它应该没问题:

public class Example
{
    public void Test()
    {
        var t1 = new List<Table1>();
        var t2 = new List<Table2>();
        var t3 = new List<Table3>();
        var filter = "hello";
        Func<string, bool> filterFunc = (x) => x.StartsWith(filter);

        var rpt1 = t1.Where(x => filterFunc(x.Name));
        var rpt2 = t2.Where(x => filterFunc(x.Name));
        var rpt3 = t3.Where(x => filterFunc(x.Name));

    }
}

正如您所看到的,我已将过滤器抽象为function delegate

现在一个可能更好的解决方案,取决于这是否真的有意义,是将所有共享列放入一个基类,所有这些都来自:

public class TableCommon
{
    public string Name { get; set; }
}

public class Table1 : TableCommon
{}

public class Table2 : TableCommon
{}

public class Table3 : TableCommon
{}


public class Example
{

    public void Test2()
    {
        var t1 = new List<Table1>();
        var t2 = new List<Table2>();
        var t3 = new List<Table3>();

        var rpt1 = FilterData(t1);
        var rpt2 = FilterData(t2);
        var rpt3 = FilterData(t3);

    }

    public IEnumerable<T> FilterData<T>(IEnumerable<T> data) where T : TableCommon
    {
        var filter = "hello";
        Func<T, bool> pred = (x) => x.Name.StartsWith(filter);
        return data.Where(pred);
    }

}

现在你可以隐藏你的过滤器逻辑,甚至可以通过使pred变量成为参数并允许这个函数更通用来传递不同的过滤器。

现在,如果您对使用基类和FilterData上的Type约束不熟悉,那么您将不得不使用反射,我必须出于其他原因这样做,并且它变得非常混乱且非常难以理解快速。那个或许像dynamic linq这样的东西可能会非常混乱。