尝试在扩展方法中创建ObservableCollection的异常

时间:2013-02-28 19:10:43

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

我们在视图模型中使用ObservableCollections,因为我们正在使用MVVM,为了节省一些输入,我认为有一个扩展方法将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()扩展方法完全相同的事情,我会理解这一点,但是有效。

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我过去遇到过类似的问题(尤其是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

获取实体框架以允许扩展方法的一个示例是尝试概括其dbContext.Set<T>名字对象。而不是这样做:

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);
}

您可以为您的方案做类似的事情。

希望这有帮助。