【问题标题】:Exposing EntityFramework 4 entities as IList instead of IObjectSet将 EntityFramework 4 实体公开为 IList 而不是 IObjectSet
【发布时间】:2011-06-03 14:14:35
【问题描述】:

我的 Entity Framework 4 项目中有一个“客户”POCO 实体。我想将我的客户实体作为通用列表而不是 ObjectSet 公开给我的上层。

我有一个 IUnitOfWork 接口,如下所示:

public interface IUnitOfWork
{
   string Save();
   IList<Customer> Customers { get; }
}

在我的实体框架 DAL(实现上述接口)我有以下内容:

public class EntityContainer : ObjectContext, IUnitOfWork
{
    private IObjectSet<Customer> _customers;

    public IList<Customer> Customers 
    {
       get
       {
         if (_customers == null)
         {
             _customers = CreateObjectSet<Customer>("Customers");                    
         }
         return _customers.ToList<Customer>() ;
       }            
    }
}

但是,'CreateObjectSet("Customers")' 行不起作用。每次我尝试添加新的“客户”时,什么都没有发生。有趣的是,如果我恢复使用 IObjectSet,那么代码就可以工作。例如:

public interface IUnitOfWork
{
    string Save();
    IObjectSet<Contact> Contacts { get; }
}


public class EntityContainer : ObjectContext, IUnitOfWork
{
    private IObjectSet<Customer> _customers;

    public IObjectSet<Customer> Customers 
    {
       get
       {
         if (_customers == null)
         {
             _customers = CreateObjectSet<Customer>("Customers");                    
         }
         return _customers;
       }            
    }
}

IQueryable 也可以工作,但我无法让 IList 工作,我也不知道为什么。有人有什么想法吗?

#

对原始问题的更正。使用 IQueryable 不起作用,IEnumerable 也不起作用。这是因为客户存储库需要提供“添加”和“删除”方法来从实体集合中添加/删除(在上面的示例中添加或删除客户实体)。 IQueryable 或 IEnumerable 都不允许您添加或删除对象;相反,必须使用 ICollection 或 IList。这让我回到了原来的问题。我不想将我的集合作为 ObjectSet 公开给存储库。我想使用与 EntityFramework 无关的类型,即 - 我想使用通用列表。

还有其他建议吗?我怀疑有一种简单的方法可以做到这一点,但我对框架不够熟悉,无法弄清楚。

【问题讨论】:

  • IEnumerable&lt;T&gt; 更加通用。

标签: c# entity-framework-4 iqueryable


【解决方案1】:

您似乎在所有这些中都缺少一个存储库。存储库通常负责处理从 ObjectSet&lt;T&gt;IList&lt;T&gt; 的转换(或者,在大多数情况下,IEnumerable&lt;T&gt;IQueryable&lt;T&gt;)。

public class EntityContainer : ObjectContext
{
    private IObjectSet<Customer> _customers;

    public IObjectSet<Customer> Customers
    {
        get
        {
            return _customers ?? 
                ( _customers = CreateObjectSet<Customer>("Customers");
        }
    }
}

public class CustomerRepository
{
    EntityContext _context = new EntityContext();

    public IQueryable<Customer> FindAll()
    { 
        return _context.Customers;
    }

    public Customer FindById(int id)
    {
        return _context.Customers.Single(c => c.Id == id);
    }

    // And so on.
}

然后我通常让我的 UnitOfWork 创建应在工作单元中登记的存储库,以便通过存储库完成的任何操作都捆绑在一个操作中。

请记住,我的 UnitOfWork 只有两种方法。一个用于获取存储库,另一个用于提交工作单元。所有数据检索都由存储库处理。

【讨论】:

  • 嗨,我没有错过存储库或工作单元,但我没有在这里提到它们,因为它们非常简单,而且我知道它们按预期工作。我的模式实际上与您在上面描述的几乎完全相同。您说您通常使用存储库从 ObjectSet 转换为 IList。我可能会尝试这种方法,而不是在我的实体框架级别进行转换,谢谢。
【解决方案2】:

_customers.ToList() 是罪魁祸首。 ToList 执行查询并将该查询中的所有项目复制到新的集合对象中。这个新的集合对象不提供 ObjectSet 所具有的跟踪功能。

【讨论】:

  • 好的,这是很好的信息,谢谢。根据您的 cmets 和 Justin 之前的帖子,我应该坚持使用 IEnumerable、IQueryable,或者在更改 ObjectSet 后在我的代码中的其他位置执行到 IList 的转换,在这一点上,我不再关心 ObjectSet 的跟踪功能。再次感谢!
  • 我很乐意..但是我现在正在测试这个问题仍然存在。当我之前说 IQueryable 有效时,我是不正确的。我的“Find()”方法适用于 IQueryable,但我的客户存储库中的“添加”和“删除”方法将不起作用,因为您无法添加到 IEnumerable。为此,您必须使用 ICollection 或 IList,这让我回到了原来的问题。我需要将我的实体公开为一个可以添加和删除的集合,但我不能使用 ObjectSet 类型。有什么建议吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
相关资源
最近更新 更多