加载实体的特定属性并将其指定为另一个实体的引用

时间:2012-09-21 13:49:38

标签: entity-framework entity-framework-4.1 ef-code-first dbcontext

示例:

我正在输入新发票。对于此发票,我需要输入客户。让我们假设我们检索了一个客户列表:

var list = Context.Set<Customer>().ToList();

我在这里看到两个问题:

1)我不需要为客户提供所有信息,我只需要ID,代码和名称

2)当前DbContext中的客户是只读的,因此如果可以告诉DbContext不监控其状态,以提高性能,那就太好了。

问题:

1)我们可以只为客户加载部分数据,但仍然可以将其分配给发票(参见下面的代码)?

2)我们可以告诉DbContext不要监视客户的变化,并且仍然可以这样做:

Invoice.Customer = CustomerList[10];

1 个答案:

答案 0 :(得分:2)

没有直接的方法可以完全你想要的东西,但是你可以通过一些妥协来实现你的目标。

  

我不需要为客户提供所有信息,我只需要ID,   代码和名称

EF无法创建部分加载的实体,但您可以创建匿名类型:

Context.Customers.Select(c => new {Id = c.CustomerId, Code = c.Code, Name = c.Name}).Tolist()

如果你可以使用新的匿名类型然后使用它,或者你可以遍历该列表,创建实际的客户对象。

  

当前DbContext中的客户是只读的,所以如果它是好的   有可能告诉DbContext不要监视他们的状态,改进   性能

EF提供AsNoTracking()的扩展名,它将完全符合您的要求:

var list = Context.Set<Customer>().AsNoTracking().ToList();

根据您从上面选择的内容,以下代码可能会更改,但此代码确实可以实现您的目标。部分加载客户,但仍允许您将客户附加到发票。

注意:您需要先将客户附加到您的上下文,然后才能使用它,然后将其设置为Unchanged状态将阻止它覆盖现有数据。

        m = new Model();

        var list = m.Customers.Select(c => new {Id = c.CustomerId, Code = c.Code, Name = c.Name});

        List<Customer> customerList = new List<Customer>();
        foreach (var item in list)
        {
            customerList.Add(new Customer()
                {
                    CustomerId = item.Id,
                    Code = item.Code,
                    Name = item.Name
                });
        }

        Invoice i = new Invoice();
        var customer = customerList.First();
        m.Customers.Attach(customer);
        m.Entry(customer).State = EntityState.Unchanged;

        i.Customer = customer;

        m.Invoices.Add(i);
        m.SaveChanges();