我可以创建一个接受多个表和泛型类型的通用CompiledQuery吗?

时间:2009-01-13 19:39:51

标签: c# linq linq-to-sql c#-3.0

我有多个带有“id”组件的表。我想使用LINQ从其中一个表中获取一个具有正确LINQ-To-SQL类型的项,但只使用一个CompiledQuery。

这是一个当前有效的例子。假设DBML中定义的对象类型是“myitem”,其表是“myitems”。

    var getOneItem = CompiledQuery.Compile(
        (MyDataContext db, long id) => ((from i in db.myitems
                                              where i.id == id
                                              select i).SingleOrDefault()));

我想做这个,其中类型可以是“myitem”,“myitems2”,或者我可能感兴趣的任何表和对象类型。

    var getOneItemAnyTable = CompiledQuery.Compile(
        (Table tab, Type T long id) => ((from anItem in tab<T>
                                              where anItem.id == id
                                              select anItem).SingleOrDefault()));

我编写了这个语法,因为我不确定这里的语法是什么样的。任何想法,如果可能的话?我是否必须使用DBML来为所涉及的类型创建某种超类?

谢谢。

2 个答案:

答案 0 :(得分:2)

而不是这样做,从实体中具有共同属性的基础实体派生所有实体(如Id)。使用POCO实现这些层将对您有所帮助。

答案 1 :(得分:1)

我很确定你不能让一个编译查询跨越多个表(如果这就是你的意思);怎么会知道在哪里看? EF通过继承(和多个表)支持这样的东西,但即使继承,LINQ-to-SQL也仅支持单表区别继承。

这个问题的核心与今天早些时候相同to this one。棘手的一点是主键,因为很难抽象地定义。其余的只是GetTable<T>(至少有LINQ-to-SQL)。

在这种情况下,您不需要超类 - 只是获取主键的一种方法。幸运的是,我似乎记得LINQ-to-SQL提供了一种方法(不需要使用属性,这不是LINQ-to-SQL的预先请求);以下不预编译(并且未经测试),但应该非常接近:

更新已修复并经过测试)

用法优先:

Foo foo = ctx.Get<Foo>(fooid);
Bar bar = ctx.Get<Bar>(barid);

代码:

    public static TItem Get<TItem, TKey>(
        this DataContext ctx, TKey key)
        where TItem : class
    {
        var table = ctx.GetTable<TItem>();
        var primaryKey = ctx.Mapping.GetMetaType(typeof(TItem))
                .DataMembers.Where(
            member => member.IsPrimaryKey).Single().Member.Name;

        var item = Expression.Parameter(typeof(TItem), "item");
        var lambda = Expression.Lambda<Func<TItem, bool>>(
            Expression.Equal(
                Expression.PropertyOrField(item, primaryKey),
                Expression.Constant(key, typeof(TKey))),
                item);
        return table.Single(lambda);
    }
    public static TItem Get<TItem>( // common case
        this DataContext ctx, int key)
        where TItem : class
    {
        return Get<TItem, int>(ctx, key);
    }
    public static TItem Get<TItem>( // common case
       this DataContext ctx, string key)
       where TItem : class
    {
        return Get<TItem, string>(ctx, key);
    }

我会看是否能找到预编译的方法......