【问题标题】:Initializing strongly typed objects in LINQ to Entities在 LINQ to Entities 中初始化强类型对象
【发布时间】:2009-09-17 17:42:12
【问题描述】:

我有一个普通的旧 CLR 对象,它本质上是两个实体框架对象的包装器,我这样做是为了将这个包装器对象传递给 MVC 框架中的强类型视图。我的 foo 包装类非常简单:

public class FooWrapper
{
    public FooWrapper(Foo f, Bar b)
    {
        this.FooObject = f;
        this.BarObject = b;
    }

    public Foo FooObject { get; private set; }
    public Bar BarObject { get; private set; }
}

到目前为止,我的 ListFoosWithBars 函数如下:

public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
{
    IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
    IEnumerable<FooWrapper> results = (from f in _entities.FooSet
                                       join b in tempBar on f.ID equals b.foos.ID
                                       select new FooWrapper(f, b));
    return results;
}

这不起作用,因为显然 LINQ to Entities 不支持参数化初始化,因此会抛出一个异常,上面写着:“LINQ to Entities 中仅支持无参数构造函数和初始化程序。”我想知道是否有另一种方法可以达到同样的效果?

【问题讨论】:

    标签: linq entity-framework linq-to-entities strong-typing


    【解决方案1】:

    如果您向 FooWrapper 添加无参数构造函数,然后改用对象初始化,如下所示:

    public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
    {
        IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
    
        IEnumerable<FooWrapper> results = (
            from f in _entities.FooSet
            join b in tempBar on f.ID equals b.foos.ID
            select new FooWrapper()
            {
                FooObject = f, 
                BarObject = b
            });
    
        return results;
    }
    

    【讨论】:

    • 输入相同的东西,你赢了。
    【解决方案2】:

    好的,但是如果你希望 FooObject 和 BarObject 是只读的呢?在我看来,他们否定了在对象上使用构造函数的能力。

    我可以看到很多人为了在这种情况下利用对象初始化而破坏了良好的封装实践。

    【讨论】:

      【解决方案3】:

      你为什么不使用 .AsEnumerable()?这样,您就不需要创建无参数构造函数,这就是您想要的。

      您的代码几乎没有问题。改成这样:

      public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
      {
          IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
          IEnumerable<FooWrapper> results = (from f in _entities.FooSet.AsEnumerable()
                                             join b in tempBar on f.ID equals b.foos.ID
                                             select new FooWrapper(f, b));
          return results;
      }
      

      我今天也遇到了同样的问题。我有一个带有一个参数构造函数的类。此构造函数填充了一个私有只读字段,该字段由属性返回,仅使用 get 而不是 set。

      【讨论】:

      • 这是迄今为止解决此问题的最佳方法!
      • 我会非常小心地使用这种方法,但您基本上通过调用 AsEnumerable 来否定实体框架的好处。一旦您指定您有效地从 FooSet 表中获取所有记录,然后在内存中本地执行连接。想想当您拥有数千(或数百万)条记录时对性能的影响。
      • @Santo 同意,这种方法会导致我的机器在 16 个表上使用 LINQ 语句停止,大约需要五分钟才能返回结果。使用类似的 SQL 语句几乎可以瞬间完成。
      【解决方案4】:

      尝试不同的初始化:

      public class FooWrapper
      {
          public FooWrapper() { }
      
          public Foo FooObject { get; set; }
          public Bar BarObject { get; set; }
      }
      
      
      public IEnumerable<FooWrapper> ListFoosWithBars(int userID)
      {
          IEnumerable<Bar> tempBar = ListBarsByUserID(userID);
      
          IEnumerable<FooWrapper> results = (
              from f in _entities.FooSet
              join b in tempBar on f.ID equals b.foos.ID
              select new FooWrapper 
              {
                  FooObject = f,
                  BarObject = b
              });
      
          return results;
      }
      

      【讨论】:

        【解决方案5】:
        猜你喜欢
        • 1970-01-01
        • 2012-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 1970-01-01
        • 1970-01-01
        • 2015-07-31
        相关资源
        最近更新 更多