实体框架4.1:具有“DefaultOrder属性”的存储库

时间:2011-04-23 19:16:25

标签: entity-framework c#-4.0 linq-to-entities sql-order-by

使用以下代码(简化)时,我收到错误

“无法将类型'System.DateTime'强制转换为'System.Object'.LINQ to Entities仅支持转换实体数据模型基元类型。”

在return语句的行中:

public MyRepository<Post>
{
  public Expression<Func<Post, object>> DefaultOrder;

  public MyRepository()
  {
    DefaultOrder = p => p.PublishedOn;
  }

  public IQueryable<Post> All()
  {
    var entities = new MyDbContext().Set<Post>();
    return entities.OrderByDescending(DefaultOrder);
  }
}

我使用与db4o / db4o.Linq相同的代码而不是实体框架,没有问题。

所以我的问题在这里:

  1. 为什么会发生这种错误?
  2. 是否有替代解决方案,让我以与现在相同(相似)的方式定义我的DefaultOrder?
  3. 修改

    找到适用于我的解决方案,用订购方法替换默认订单表达式:

    public MyRepository<T>
    {
      public Func<IQueryable<T>, IOrderedQueryable<T>> DefaultOrderMethod;
    
      public MyRepository()
      {
        DefaultOrderMethod = o => o.OrderBy(x => x.PublishedOn);
      }
    
      public IQueryable<T> All()
      {
        var entities = new MyDbContext().Set<T>();
        return DefaultOrderMethod(entities);
      }
    }
    

1 个答案:

答案 0 :(得分:1)

传递给OrderBy扩展方法的第二种表达式是从表达式返回的类型推断出来的。它期待一个表达式&gt;。因此,如果您要存储排序表达式,则需要明确地为其指定TOrderBy类型。

public MyRepository<Post>
{
  public Expression<Func<Post, DateTime>> DefaultOrder;

  public MyRepository()
  {
    DefaultOrder = p => p.PublishedOn;
  }

  public IQueryable<Post> All()
  {
    var entities = new MyDbContext().Set<Post>();
    return entities.OrderByDescending(DefaultOrder);
  }
}

.NET不支持装箱/取消装箱通用参数类型,除非你使用.NET 4.0并通过协方差和逆变使用接口,这对你的例子不起作用。

这又是通用系统在.NET中的工作原理。这样的事情唯一的原因......

Query.OrderBy(x => x.PublishedOn)

...是因为TOrderBy类型可以从表达式返回类型(DateTime)中推断出来。