在LINQ到实体中键入成员支持? [英] Type member support in LINQ-to-Entities?

查看:105
本文介绍了在LINQ到实体中键入成员支持?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用实体框架模型的MVC3项目,其中我已经标记了一个类:

  public部分类Product 
{
public bool IsShipped
{
get {/ * do stuff * /}
}
}

我想在LINQ表达式中使用:

  db.Products.Where(x => x.IsShipped).Select(...); 

但是,我收到以下错误:



< blockquote>

System.NotSupportedException被用户代码未处理Message =
指定的类型成员'IsShipped'在LINQ to Entities中不受支持。
仅支持初始化,实体成员和实体导航属性
。 Source = System.Data.Entity


我已经google了,但没有找到任何关于这个用法的确定我试过:

  public partial class Product 
{
public bool IsShipped()
{
/ * do东西* /
}
}

db.Products.Where(x => x.IsShipped())。

但是我得到:


System.NotSupportedException被用户代码未处理消息= LINQ
实体不识别方法'Boolean IsShipped()'方法,
并且此方法无法转换为存储表达式。

Source = System.Data.Entity


有那里的功能,我不想建立LINQ查询本身...什么是一个很好的方法来处理这个?



*更新*



Darin使有效点指出,执行 IsShipped 中所做的任何操作都需要转换为SQL查询,编译器可能不知道如何200的X- 200 200 200 200 X- 200 200 X- 200 200: X-454545454545 X- 20045 X- 20045 X-454545 X-454545 X-454545 X-454545 X-454545 X- 20045 X- 20045 X- 20045 X- 20045 X- xp = db.Quizes
.ToList()
.Where(x =>!x.IsShipped)
.Select(x => x.Component.Product);

但它会生成此错误:


发生关系多重约束违规:
EntityReference可以有不超过一个相关对象,但是
查询返回了多个相关对象。这是一个不可恢复的
错误。


虽然好奇地这样做:

  IEnumerable< Product> xp = db.Quizes 
.ToList()
.Where(x => x.Skill.Id == 3)
.Select(x => x.Component.Product) ;

为什么会这样?



* update II *



对不起,最后一个语句不起作用...



* update III *



我正在关闭这个问题,赞成在这里建议一个解决方案,将我的逻辑展开为查询 - 讨论将转到这个新帖子<一>。将整个原始查询检索到内存中的第二种方法可能是不可接受的,但第三种将逻辑实现为数据库的直接查询仍有待探索。



感谢大家的宝贵意见。

解决方案

使这个DRY(避免重复逻辑)在 Where 子句中的 IsShipped ),并避免在应用过滤器之前将所有数据加载到内存中,以提取 IsShipped 的内容到表达式中。 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X- 20045 X-例如:

  public partial class Product 
{
public int ProductId {get;组; } //< - 映射到DB
public DateTime? ShippingDate {get;组; } //< - 映射到DB
public int ShippedQuantity {get;组; } //< - 映射到DB

//必须理解的静态表达式
//由LINQ to Entities,即可翻译成SQL
public static Expression&FunC&产品,产品>>> IsShippedExpression
{
get {return p => p.ShippingDate.HasValue&& p.ShippedQuantity> 0;
}

public bool IsShipped //< - 没有映射到DB,因为readonly
{
//将表达式编译成委托Func< Product,bool> X-4545454545 X- 20045 X-454545 X-454545 X- 20045 X-454545 X-4545 X- 20045 X-454545 X- 20045 X-454545 X- 20045 X-454545 X- }
}
}

您可以像这样执行查询: / p>

  var result = db.Products.Where(Product.IsShippedExpression).Select(...)ToList(); 

这里你只能有一个地方放置逻辑( IsShippedExpression ),然后将其用于数据库查询,并在您的 IsShipped 属性中。



我会做这个吗在大多数情况下可能不是,因为编译表达式很慢。除非逻辑非常复杂,否则可能会发生变化,而且我使用 IsShipped 的性能无关紧要,所以我会重复逻辑。常常可以将常用的过滤器提取到扩展方法中:

  public static class MyQueryExtensions 
{
public static IQueryable< Product> WhereIsShipped(
this IQueryable< Product> query)
{
return query.Where(p => p.ShippingDate.HasValue&& p.ShippedQuantity> 0);
}
}

然后以这种方式使用:

  var result = db.Products.WhereIsShipped()。选择(...)ToList(); 

你会有两个地方,但维护逻辑: IsShipped < 200新200新新新新旗新新旗旗新200新新新新旗新新旗旗新200新新新新旗新新旗200新新新新旗新新旗200新新新新旗新新旗旗

I have an MVC3 project using the Entity Framework model in which I've marked up a class like this:

public partial class Product
{
    public bool IsShipped
    {
        get { /* do stuff */ }
    }
}

and which I want to use in a LINQ expression:

db.Products.Where(x => x.IsShipped).Select(...);

however, I get the following error:

System.NotSupportedException was unhandled by user code Message=The specified type member 'IsShipped' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported. Source=System.Data.Entity

I've googled but not found anything definitive about this usage to I tried:

public partial class Product
{
    public bool IsShipped()
    {
        /* do stuff */
    }
}

db.Products.Where(x => x.IsShipped()).Select(...);

but then I get:

System.NotSupportedException was unhandled by user code Message=LINQ to Entities does not recognize the method 'Boolean IsShipped()' method, and this method cannot be translated into a store expression.
Source=System.Data.Entity

there's functionality there that I don't want to build into the LINQ query itself... what's a good way to handle this?

* update *

Darin makes the valid point that whatever is done in the implementation of IsShipped would need to be converted to a SQL query and the compiler probably doesn't know how to do it, thus retrieving all objects into memory seems the only choice (unless a direct query to the database is made). I tried it like this:

IEnumerable<Product> xp = db.Quizes
    .ToList()
    .Where(x => !x.IsShipped)
    .Select(x => x.Component.Product);

but it generates this error:

A relationship multiplicity constraint violation occurred: An EntityReference can have no more than one related object, but the query returned more than one related object. This is a non-recoverable error.

though curiously this works:

IEnumerable<Product> xp = db.Quizes
    .ToList()
    .Where(x => x.Skill.Id == 3)
    .Select(x => x.Component.Product);

why would that be?

* update II *

sorry, that last statement doesn't work either...

* update III *

I'm closing this question in favour of pursuing a solution as suggested here to flatten my logic into a query - the discussion will move to this new post. The second alternative, to retrieve the entire original query into memory, is likely unacceptable, but the third, of implementing the logic as a direct query to the database, remain to be explored.

Thanks everyone for the valuable input.

解决方案

The only way to make this "DRY" (avoid repeating the logic inside of IsShipped in the Where clause again) and to avoid loading all data into memory before you apply the filter is to extract the content of IsShipped into an expression. You can then use this expression as parameter to Where and in IsShipped as well. Example:

public partial class Product
{
    public int ProductId { get; set; }           // <- mapped to DB
    public DateTime? ShippingDate { get; set; }  // <- mapped to DB
    public int ShippedQuantity { get; set; }     // <- mapped to DB

    // Static expression which must be understood
    // by LINQ to Entities, i.e. translatable into SQL
    public static Expression<Func<Product, bool>> IsShippedExpression
    {
        get { return p => p.ShippingDate.HasValue && p.ShippedQuantity > 0; }
    }

    public bool IsShipped // <- not mapped to DB because readonly
    {
        // Compile expression into delegate Func<Product, bool>
        // and execute delegate
        get { return Product.IsShippedExpression.Compile()(this); }
    }
}

The you can perform the query like so:

var result = db.Products.Where(Product.IsShippedExpression).Select(...).ToList();

Here you would have only one place to put the logic in (IsShippedExpression) and then use it for database queries and in your IsShipped property as well.

Would I do this? In most cases probably no, because compiling the expression is slow. Unless the logic is very complex, likely a subject to change and I am in a situation where the performance of using IsShipped doesn't matter, I would repeat the logic. It's always possible to extract often used filters into an extension method:

public static class MyQueryExtensions
{
    public static IQueryable<Product> WhereIsShipped(
        this IQueryable<Product> query)
    {
        return query.Where(p => p.ShippingDate.HasValue && p.ShippedQuantity >0);
    }
}

And then use it this way:

var result = db.Products.WhereIsShipped().Select(...).ToList();

You would have two places though the maintain the logic: the IsShipped property and the extension method, but then you can reuse it.

这篇关于在LINQ到实体中键入成员支持?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆