我们在应用程序中引入了一项新功能,它会影响数百个查询。我们必须设置一个bool
字段,以非常复杂的方式指示许可证是否有效。
我想创建一个返回此bool
值的方法,并且我想在每个查询中使用它。问题是,如果我以下面显示的方式使用它,它会为每个结果执行单独的查询。
如何以编译为SQL并作为单个查询执行的方式使用Expression
?
原始查询,需要改进
IQueryable<DeviceMinimal> devices =
from device in db.Devices
where device.AccountId = accountId
select new DeviceMinimal
{
Id = device.Id,
Name = device.Name,
LicenseIsValid = !checkForLicense ||
device.License != null && (
!device.License.TrialStarted
// && 12+ licensing rules
)
};
checkForLicense
是bool
,表示不需要检查许可证。它在某些情况下使用,有必要加以考虑。
解决问题的代码,但会为每个设备引发单独的查询
IQueryable<DeviceMinimal> devices =
from device in db.Devices
where device.AccountId = accountId
select new DeviceMinimal
{
Id = device.Id,
Name = device.Name,
LicenseIsValid =
LicenseHelper.IsLicenseValid(checkForLicense).Invoke(device)
};
上述查询中使用的方法:
public static Func<Device, bool> IsLicenseEnabledAndValid(bool checkForLicense)
{
return result => !checkForLicense ||
result.License != null && (
!result.License.TrialStarted
// && 12+ licensing rules
);
}
答案 0 :(得分:0)
如果您在查询之前设置DataLoadOptions
的{{1}}并将其设置正确,则应避免使用子选择。类似的东西:
DataContext
Tha是默认行为(实体的延迟加载)。您可以获取更多信息,搜索&#39; linq到sql eagerloading&#39;
答案 1 :(得分:0)
不确定它是否可行,但您是否尝试在主查询中访问许可证? 换句话说就像:
Queryable<DeviceMinimal> devices =
from device in db.Devices
where device.AccountId = accountId
select new DeviceMinimal
{
Id = device.Id,
Name = device.Name,
LicenseIsValid =
LicenseHelper.IsLicenseEnabledAndValid(checkForLicense).Invoke(device.Licence)
};
public static Func<License, bool> IsLicenseEnabledAndValid(bool checkForLicense)
{
return result => !checkForLicense ||
result != null && (
!result.TrialStarted
// && 12+ licensing rules
);
}
如果您需要在方法中同时访问设备和许可证,则可能需要将功能更改为
public static Func<Device, License, bool> IsLicenseEnabledAndValid(bool checkForLicense)
{
return (device, licence) =>
...
}