Linq到SQL表达式属性,可以转换为SQL

时间:2011-12-11 20:03:51

标签: c# linq linq-to-sql

我有一个LINQ to SQL类,我们称之为Test,我希望能够使用LINQ查询访问属性,但我得到了着名的“No Supported Translation to SQL”运行时错误。我对概念问题很感兴趣。这是我的简化课程:

public class Test
{ 
  public int ID {get; set;} // Stored in Database
  public int NonForeignKeyValue {get; set;} // Stored in Database
}

这是我正在尝试完成的一个示例,但我不希望总是在LINQ中明确地编写连接的开销:

var db = (new DataContext()).GetTable<Test>();
var q = (from t in db.GetTable<Test>()
         join o in db.GetTable<OtherTable>() on o.ID equals t.ID
         where t.OtherStuff
         select t)

我希望能够向Test添加一个属性,告诉我OtherTable中是否有可以与Test结合的行:

  public bool IsInOtherTable
  {
    get
    {
       return (new DataContext())
              .GetTable<OtherTabke>()
              .Any(x => x.NonForeignKeyValue == this.NonForeignKeyValue));
    }
  }

最终这就是我希望我的代码看起来像,但它错误。我基本上想要返回包含一些数据库计算值的所有条目:

using (DataContext db =  new DataContext())
{
   var q = db.GetTable<Test>()
             .Where(x => x.IsInOtherTable && x.OtherStuff); //Error
}       

我基本上试图保存自己每次编写此代码时,我想检查Test是否在另一个表中有某些信息。我对我描述的确切问题不感兴趣,我对如何在概念上将连接部分添加到SQL并仍使用LINQ更感兴趣。我猜我使用Linq.Expression,但我真的不知道,我不知道该怎么做。

顺便说一句,我可以编写实际的SQL,因为它并不复杂,但我想知道如何解决这个问题仍然使用LINQ。

编辑:我试过这个属性,但是我得到了同样的错误。将返回类型更改为Expression ...

更复杂
public System.Linq.Expressions.Expression<Func<Article3, bool>> Exists
{
    get
    {
       using (DataContext db =  new DataContext())
       {
         return i => db.GetTable<OtherTable>()
                       .Any(x => x.NonForeignKeyValue == i.NonForeignKeyValue));
       }
    }
}        

2 个答案:

答案 0 :(得分:1)

每次linq生成器将代码转换为查询时,都必须处理表达式树。

在你的例子中,你没有传递表达式,而是 - 属性,委托,即表达式访问者无法“进入”的东西。

一般情况下,请尝试重新考虑您的条件,以便bool代替Expression<T, bool>等。

http://netpl.blogspot.com/2008/02/linq-to-object-vs-linq-to-sql-and.html

答案 1 :(得分:0)

首先,我认为你可能会高估“始终在LINQ中明确编写连接的开销”。这是一个额外的代码行,它具有相对自我记录的优势,就像你正在做的事情一样(总是一件好事),而任何其他方法都将首先转变为SQL,然后转变为一个查询计划。至少执行成本高,可能更昂贵(SQLServer是一个很好的连接!)

尽管如此,我还是可以想到两种选择。

一个是在类上有一个EntityRef属性,用于定义与另一个表的这种关系。然后,您可以测试查询中是否为null(如果它位于一对多关系的另一侧,则为EntitySet。)

另一种是定义一个返回bit结果的SQL函数,该结果指示id是否引用与另一个表相关或不相关的行。

然后在DataContext派生类上定义一个与C#术语中的签名匹配的受保护方法,并将Function attribute映射到该SQL函数。 (因为这不是你可以在C#版本中提供合理的非db-using版本的东西,你可以通过调用ExecuteMethodCall来实现C#函数。)

然后您可以使用该方法代替连接。

尽管如此,这在代码中可能不太明显,并且存在效率低于仅仅保持连接的风险。