我有这样的事情:
var adrsQuery = (from a in this.Context.Addresses
where myList.Contains(a.Address_K)
select new AlternateAddressesDB()
{
Line1 = GetAddressLine1(a.AddressLine1),
Line2 = a.AddressLine2,
City = a.City,
State = a.State,
ZipCode = a.ZipCode
}).ToList();
private static string GetAddressLine1(string adrs)
{
if (string.IsNullOrWhiteSpace(adrs))
adrs = "Medical Office";
return adrs;
}
问题出在Line1 = GetAddressLine1(a.AddressLine1),
看起来我不能在那里调用一个方法,我怎么能在方法中执行这个逻辑而不用那样调用它?
答案 0 :(得分:4)
问题不在于LINQ。您正在使用ORM将您正在编写的LINQ转换为SQL。它无法翻译任意方法调用。您需要对查询结果进行转换。
所以 - 获取结果,不用尝试内联调用GetAddressLine1
。然后,您可以使用Select
再次投影结果来修复数据......例如:
var adrsQuery = this.Context.Addresses
.Where(a => myList.Contains(a.Address_K))
.AsEnumerable()
.Select(a => new AlternateAddressesDB
{
Line1 = GetAddressLine1(a.AddressLine1),
Line2 = a.AddressLine2,
City = a.City,
State = a.State,
ZipCode = a.ZipCode
}).ToList();
private static string GetAddressLine1(string adrs)
{
if (string.IsNullOrWhiteSpace(adrs))
adrs = "Medical Office";
return adrs;
}
答案 1 :(得分:4)
其他人已经向您解释了这个问题。您无法在SQL服务器上执行C#方法...
通常您尝试更改查询:
var adrsQuery = (from a in this.Context.Addresses
where myList.Contains(a.Address_K)
select new AlternateAddressesDB()
{
Line1 = a.AddressLine1 == null || a.AddressLine1.TrimEnd() == string.Empty ? "Medical Office" : a.AddressLine1,
Line2 = a.AddressLine2,
City = a.City,
State = a.State,
ZipCode = a.ZipCode
}).ToList();
或者你强制在本地执行你的方法:
var adrsQuery = (from a in this.Context.Addresses
where myList.Contains(a.Address_K)
select new AlternateAddressesDB()
{
Line1 = a.AddressLine1,
Line2 = a.AddressLine2,
City = a.City,
State = a.State,
ZipCode = a.ZipCode
})
.AsEnumerable() // From here the query is executed "locally"
.Select(a => new AlternateAddressesDB()
{
Line1 = GetAddressLine1(a.Line1),
a.Line2,
a.City,
a.State,
a.ZipCode
})
.ToList();
您从数据库加载您需要的数据,然后在本地创建一组新的对象,数据“被操纵”
(这个第二个解决方案通常只能在最后的.Select()
中使用,因为如果你在本地执行一个完整的.Where()
,你要求服务器有太多行,然后你跳过很多他们)
还有第二个/第三个选项:https://stackoverflow.com/a/29128874/613130
几天前他们问我如何解决类似的问题。看看我给出的解决方案示例。限制是您需要能够将方法转换为可由Entity Framework执行的命令(因此您需要将.IsNullOrWhiteSpace()
转换为可以发送到SQL的内容),例如:
[Expandable]
static string GetAddressLine1(Address address)
{
// Not necessary to implement, see linked answer
throw new NotImplementedException();
}
static Expression<Func<Address, string>> GetAddressLine1Expression()
{
return x => x.AddressLine1 == null || x.AddressLine1.TrimEnd() == string.Empty ? "Medical Office" : x.AddressLine1;
}
请注意,这条道路要复杂得多,我不建议那些胆小的人,或者那些可以追随更轻松道路的人(我个人不会使用它)
答案 2 :(得分:3)
这样做,
var adrsQuery = this.Context.Addresses
.Where(a => myList.Contains(a.Address_K))
.ToList() // This line executes the IQueryable and returns an IEnumerable.
.Select(a => new AlternateAddressesDB
{
Line1 = GetAddressLine1(a.AddressLine1),
Line2 = a.AddressLine2,
City = a.City,
State = a.State,
ZipCode = a.ZipCode
}).ToList();
private static string GetAddressLine1(string adrs)
{
if (string.IsNullOrWhiteSpace(adrs))
adrs = "Medical Office";
return adrs;
}
where子句将在服务器端执行,这是好的,你不会返回不必要的数据。使用非数据库函数的转换将在本地完成。
答案 3 :(得分:2)
我认为这个问题的关键是this.Context
,我认为这是一些问题。所以你的linq查询被转换为sql,它不能包含方法调用。但是你的方法很简单,你可以在查询中内联逻辑
a.AddressLine1 ?? "value"
是的,它不完全相同,但你明白了。