C# 可转换为SQL的Linq到SQL表达式属性
我有一个LINQ-to-SQL类,我们称之为C# 可转换为SQL的Linq到SQL表达式属性,c#,linq,linq-to-sql,C#,Linq,Linq To Sql,我有一个LINQ-to-SQL类,我们称之为Test,我希望能够使用LINQ查询访问属性,但我遇到了著名的“不支持转换为SQL”运行时错误。我对概念问题感兴趣。这是我的简化课程: public class Test { public int ID {get; set;} // Stored in Database public int NonForeignKeyValue {get; set;} // Stored in Database } 下面是我试图实现的一个示例,但我不希望总
Test
,我希望能够使用LINQ查询访问属性,但我遇到了著名的“不支持转换为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)
最终,这就是我希望我的代码看起来的样子,但它会出错。我基本上希望返回包含一些数据库计算值的所有条目:
using (DataContext db = new DataContext())
{
var q = db.GetTable<Test>()
.Where(x => x.IsInOtherTable && x.OtherStuff); //Error
}
使用(DataContext db=newdatacontext())
{
var q=db.GetTable()
.Where(x=>x.IsInOtherTable&&x.OtherStuff);//错误
}
基本上,每次我想检查测试是否在另一个表中有某些信息时,我都试图避免编写这些代码。我对我描述的问题不太感兴趣,我更感兴趣的是如何在概念上将连接部分添加到SQL中,并且仍然使用LINQ。我猜我用的是Linq.Expression,但我真的不知道,也不知道该怎么做
顺便说一句,我可以编写实际的SQL,因为它没有那么复杂,但我想知道如何绕过这个问题,并且仍然使用LINQ
编辑:我尝试了这个属性,但得到了相同的错误。更复杂的是,只需将返回类型更改为表达式
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));
}
}
}
public System.Linq.Expressions.Expression存在
{
得到
{
使用(DataContext db=newdatacontext())
{
返回i=>db.GetTable()
.Any(x=>x.NonForeignKeyValue==i.NonForeignKeyValue));
}
}
}
每次linq生成器将代码转换为查询时,它都必须处理表达式树
在您的示例中,您传递的不是表达式,而是-属性、委托,即表达式访问者无法“介入”的内容
总的来说,试着重新考虑你的条件,这样你就没有了bool
,而是有了Expression
等等
首先,我认为您可能高估了“总是显式地在LINQ中编写连接的开销”。这是一个额外的代码行,它的优点是可以相对地自我记录您正在做的事情(总是一件好事),任何其他方法都将首先转换为SQL,然后转换为一个查询计划,该计划的执行成本至少与SQL相同,可能更高(SQLServer是一个很好的连接!) 尽管如此,我仍能想到两种选择 一种是在类上有一个属性,该属性定义了与另一个表的关系。然后,您可以测试它在查询中是否为null(或者
EntitySet
如果它位于一对多关系的另一端)
另一个是定义一个SQL函数,该函数返回一个位
结果,指示id是否引用与另一个表相关的行
然后在DataContext派生类上定义一个受保护的方法,该方法与C#术语中的签名相匹配,并将其映射到该SQL函数。(由于这不是可以在C#version中提供合理的非db使用版本的,因此可以通过调用来实现C#函数)
然后可以使用该方法而不是join
尽管如此,这在代码中可能不太容易解释,并且有可能比仅保留联接效率更低。对于初学者,所有要一起使用的查询都必须使用相同的数据上下文是否嵌套使用(…)块折叠为一个使用(…)块?这是如何工作的?你的链接有一些关于表达式的信息,但它不能解决你想再次到数据库获取更多信息的情况…谢谢。我要试着走整条路。我的目标是尽可能地抽象出复杂性,因为我使用的是高度规范化的模式。我基本上是在尝试实现功能,然后如果(更像是什么时候)出现性能问题,我可以解决它们。这可能会落入需要在以后解决的问题中。
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));
}
}
}