我使用LINQ to Entities(EF5)来获取和过滤现有数据库中的产品列表。产品的价格可能或可能 没有折扣(统一费率或百分比)。我想在服务器端进行计算,以便我可以轻松地进行过滤,排序和 检索折扣价格,而不是写一些重复的Linq,并在顶部重新计算一些客户端代码。
我知道Linq无法将客户端功能神奇地转换为SQL,但我理解我可以写一个Expression 可以转换为SQL。看起来我应该能够编写一个Expression并将该值存储为"列。"
我已经看到了一些看似符合我要求的例子:
http://blog.cincura.net/230786-using-custom-properties-as-parameters-in-queries-in-ef/
Include derived property into a linq to entity query
麻烦的是,我无法让表达式/属性在基本级别上运行。暂时忘记折扣计算......
下面,我有一个简单的表达式来评估为" true"如果产品ID大于3.我有一个属性 产品型号返回表达式的结果。当我尝试获取属性时,我得到一个NotSupportedException: "指定的类型成员'测试' LINQ to Entities不支持。仅初始化程序,实体成员和实体导航 支持属性。"
public partial class ProductList
{
protected void Page_Load(object sender, EventArgs e)
{
using (var db = new eTailerContext())
{
var products = db.products
.Select(p => new
{
id = p.id,
name = p.name,
mytest = p.test
});
}
}
}
public class Product
{
public id { get; set; }
public name { get; set; }
public bool test
{
get { return testExpression.Compile()(this); }
}
public static Expression<Func<Product, bool>> testExpression
{
get { return t => t.id > 3; }
}
}
或者,我已尝试
mytest = Product.testExpression.Compile()(p)
但是会抛出一个不同的NotSupported异常:&#34; LINQ表达式节点类型&#39; Invoke&#39; LINQ to Entities不支持。&#34; 真的没办法做到这一点吗?这似乎是一个非常普遍的需求。
以下是配置代码:
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
this.HasKey(t => t.id);
this.ToTable("Products");
this.Property(t => t.id).HasColumnName("ProductID");
this.Property(t => t.name).HasColumnName("ProductName").HasMaxLength(255);
this.Ignore(t => t.test);
}
}
public class MyDbContext : DbContext
{
public DbSet<Product> products { get; set; }
public MyDbContext() : base("Name=SiteSqlServer")
{ }
static MyDbContext()
{
Database.SetInitializer<MyDbContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{ modelBuilder.Configurations.Add(new ProductMap()); }
}
答案 0 :(得分:2)
您需要将整个select包装为表达式。
public class Product
{
public int id { get; set; }
public string name { get; set; }
public bool test
{
get { return id > 3;}
}
public static Expression<Func<Product, dynamic>> TestExpression =
p => new
{
id = p.id,
name = p.name,
mytest = p.id > 3
};
}
然后你可以使用
var products = db.products
.Select(Product.TestExpression);
将生成和
之类的SQL语句SELECT
[Extent1].[ProductID] AS [ProductID],
[Extent1].[ProductName] AS [ProductName],
CASE WHEN ([Extent1].[ProductID] > 3) THEN cast(1 as bit) WHEN ( NOT ([Extent1].[ProductID] > 3)) THEN cast(0 as bit) END AS [C1]
FROM [dbo].[Products] AS [Extent1]
注意:您应该使用真正的类而不是动态