使用LINQ to Entities时,有没有办法在其他选择的stements中重用选择语句的块?
例如,在下面的代码中,我使用LINQ从我的数据库中选择客户设备对象。我还从连接到客户设备表的表中选择一个相关的Model对象。
list = context.PTT_CUSTOMER_DEVICES
.Include(...)
.Select(d => new CustomerDevice
{
customerAssetTag = d.CustomerAssetTag,
customerDeviceID = d.CustomerDeviceID,
//This section is used in several LINQ statements throughout the application.
Model = new Model()
{
ModelID = d.PTS_MODELS.ModelID,
Name = d.PTS_MODELS.Name,
Make = new Make()
{
MakeID = d.PTS_MODELS.PTS_MAKES.MakeID,
Name = d.PTS_MODELS.PTS_MAKES.Name
}
}
})...
但是,数据库中还有其他对象也引用了Model表。在我对其他表的select语句中,我基本上将相同的Model = new Model()代码复制到那些不同表的select语句中。
我想知道的是,是否可以在多个选择中存储和重用该代码块?可能使用扩展方法?
答案 0 :(得分:1)
作为Func<>
的替代方案,您还可以使用扩展方法重用实体类型与其他POCO之间的转换。
public static IQueryable<CustomerDevice> ToCustomerDevice(this IQueryable<PTT_CUSTOMER_DEVICES> devices)
{
return devices.Select(d => new CustomerDevice
{
customerAssetTag = d.CustomerAssetTag,
customerDeviceID = d.CustomerDeviceID
}
}
但是,EF不允许您嵌套这些,并且会抱怨它无法将嵌套扩展方法转换为SQL。
解决这个问题的方法是在内存中执行转换,而不是在SQL中执行转换:
public static Model ToModel(this PTS_MODELS model)
{
return new Model()
{
ModelID = model.ModelID,
Name = model.Name,
Make = new Make()
{
MakeID = model.PTS_MAKES.MakeID,
Name = model.PTS_MAKES.Name
}
};
}
public static IEnumerable<CustomerDevice> ToCustomerDevice(this IQueryable<PTT_CUSTOMER_DEVICES> devices)
{
return devices
.Include(d => d.PTS_MODELS.PTS_MAKES)
.AsEnumerable() // Evaulate everything that follows in memory
.Select(d => new CustomerDevice
{
customerAssetTag = d.CustomerAssetTag,
customerDeviceID = d.CustomerDeviceID,
Model = d.PTS_MODELS.ToModel()
});
}
由于您现在返回IEnumerable<>
任何进一步的Where()
条件将在内存中而不是在SQL中进行评估,因此ToCustomerDevice()
是您最后一次调用的重要性。
答案 1 :(得分:0)
如果这些表具有公共基类或实现相同的接口,则可以执行此操作。
为简单起见假设我有一个IQueryable<string> names
。我可以这样排序:
IQueryable<string> sorted = names.OrderBy(name => name);
但如果我想稍后使用这种特殊类型,我可以这样做:
Func<IQueryable<string>, IQueryable<string>> orderBy = q => q.OrderBy(x => x);
现在打电话给我,我只是传递IQueryable<string>
:
IQueryable<string> sorted = orderBy(names);
答案 2 :(得分:0)
您需要为Model
创建一个CustomerDevice
的构造函数吗? (该实体适用于PTT_CUSTOMER_DEVICES
:
public Model(CustomerDevice d) {
ModelID = d.PTS_MODELS.ModelID;
Name = d.PTS_MODELS.Name;
Make = new Make() {
MakeID = d.PTS_MODELS.PTS_MAKES.MakeID,
Name = d.PTS_MODELS.PTS_MAKES.Name
};
}
然后你可以在LINQ中调用那个构造函数:
Model = new Model(d),
答案 3 :(得分:0)
您可以使用表达式:
public static Expression<Func<PTT_CUSTOMER_DEVICES, CustomerDevice>>
CustomerDeviceExpression = d =>
new CustomerDevice
{
customerAssetTag = d.CustomerAssetTag,
customerDeviceID = d.CustomerDeviceID,
Model = new Model()
{
ModelID = d.PTS_MODELS.ModelID,
Name = d.PTS_MODELS.Name,
Make = new Make()
{
MakeID = d.PTS_MODELS.PTS_MAKES.MakeID,
Name = d.PTS_MODELS.PTS_MAKES.Name
}
}
};
然后:
list = context.PTT_CUSTOMER_DEVICES
.Include(...)
.Select(CustomerDeviceExpression)...