【问题标题】:Exception trying to create an ObservableCollection in an extension method尝试在扩展方法中创建 ObservableCollection 的异常
【发布时间】:2013-02-15 03:02:19
【问题描述】:

当我们使用 MVVM 时,我们在视图模型中使用了相当多的 ObservableCollections,为了节省一些输入,我决定有一个扩展方法将 IEnumerable 直接转换为 ObservableCollection,而不是必须创建每次都有一个新的 ObservableCollection。

因此,而不是键入...

ObservableCollection fred = new ObservableCollection(myCollection);

...我们可以输入...

ObservableCollection fred = myCollection.ToObservableCollection();

显然,在上面的人为示例中,这样做几乎没有什么好处,但在更大的 Linq 查询中,这可以清理代码。

反正我写了这样一个简单的扩展方法……

public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> collection) {
  if (collection != null) {
    return new ObservableCollection<T>(collection);
  }
  throw new ArgumentNullException("collection");
}

但是,当我尝试使用它时,我得到了一个异常......

LINQ to Entities 无法识别方法 'System.Collections.ObjectModel.ObservableCollection`1[VisionRT.CRM.Entities.SiteOverview] ToObservableCollection[SiteOverview](System.Collections.Generic.IEnumerable`1[VisionRT.CRM.Entities .SiteOverview])' 方法,并且该方法不能翻译成商店表达式。

如果不是因为 ToList() 扩展方法做了完全相同的事情,但确实有效,我会理解这一点。

任何人知道我的方法为什么失败,以及如何解决它?谢谢。

【问题讨论】:

    标签: linq-to-entities extension-methods observablecollection


    【解决方案1】:

    我认为问题在于您正在针对 enrity 框架运行查询。查询实际上是在 sql server 上运行的。因为那里不支持您的扩展方法(与列出相反)它失败了。

    【讨论】:

    • 这就是我的想法,但如果是这样,ToList 方法是如何工作的?这也是针对 EF 运行的,也无法转换为 store 方法。
    • 谁能回答这个问题?
    【解决方案2】:

    我过去也遇到过类似的问题(尤其是使用 LINQ-to-Entities),一般的解决方案是使用Expression Trees 在编译时构建 LINQ,而不是将其推迟到运行时。

    你试过了吗:

    public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> collection)
    {
        var observableCollection = new ObservableCollection<T>();
    
        foreach (var item in collection)
        {
            observableCollection.Add(item);
        }
    
        return observableCollection;
    }
    

    我不知道这是否会有所不同,但值得一试。

    至于omer schleifer's answer

    让 Entity Framework 允许扩展方法的一个示例是尝试概括其 dbContext.Set&lt;T&gt; 绰号。而不是这样做:

    dbContext.People.Where(p => p.Id == 1234);
    

    我希望能够做到这一点:

    dbContext.Get<Person>(p => p.Id == 1234);
    

    此方法无效:

    public static T Get<T>(this DapperDbContext dbContext, int id, string property = "Id") where T : class
    {
        return dbContext.Set<T>().FirstOrDefault(t => (int)t.GetType().GetProperty(property).GetValue(t) == id);
    }
    

    但是,这个确实有效:

    public static T Get<T>(this DapperDbContext dbContext, int id, string property = "Id") where T : class
    {
        var parameter = Expression.Parameter(typeof(T));
        var lambda = Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(parameter, property)
            , Expression.Constant(id)), parameter);
        return dbContext.Set<T>().FirstOrDefault(lambda);
    }
    

    您也许可以为您的场景做类似的事情。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2016-04-20
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多