1

当我们使用 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() 扩展方法做了完全相同的事情,但可以工作,我会理解这一点。

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

4

2 回答 2

0

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

于 2013-02-28T19:21:46.190 回答
0

过去我遇到过类似的问题(尤其是使用 LINQ-to-Entities),一般的解决方案是使用表达式树在编译时构建 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 的回答

让 Entity Framework 允许扩展方法的一个例子是试图概括它的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);
}

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

希望这可以帮助。

于 2013-03-08T12:23:21.370 回答