如何用EF填充我的基础客户

时间:2016-09-07 15:12:15

标签: c# entity-framework linq

首先查看我的班级结构。

public class CustomerBase
{
    public int CustomerID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string Address1 { get; set; }
    public string Address2 { get; set; }

    public string Phone { get; set; }
    public string Fax { get; set; }

}

public class Customer : CustomerBase
{
    public virtual List<Addresses> Addresses { get; set; }
}

public class Addresses
{
    [Key]
    public int AddressID { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public bool IsDefault { get; set; }
    public virtual List<Contacts> Contacts { get; set; }

    public int CustomerID { get; set; }
    public virtual Customer Customer { get; set; }
}

public class Contacts
{
    [Key]
    public int ContactID { get; set; }

    public string Phone { get; set; }
    public string Fax { get; set; }
    public bool IsDefault { get; set; }

    public int AddressID { get; set; }
    public virtual Addresses Customer { get; set; } 

}

public class TestDBContext : DbContext
{
    public TestDBContext()
        : base("name=TestDBContext")
    {
    }

    public DbSet<Customer> Customer { get; set; }
    public DbSet<Addresses> Addresses { get; set; }
    public DbSet<Contacts> Contacts { get; set; }
}

现在这种方式我试图填充我的客户群,但收到错误。

    var bsCustomer1 = (from c in db.Customer
                       where (c.CustomerID == 2)
                       select new
                       {
                           CustomerID = c.CustomerID,
                           FirstName = c.FirstName,
                           LastName = c.LastName,
                           Addresses = (from ad in c.Addresses
                                        where (ad.IsDefault == true)
                                        from cts in ad.Contacts
                                        where (cts != null && cts.IsDefault == true)
                                        select ad).ToList(),
                       }).ToList()
            .Select(x => new CustomerBase
            {
                CustomerID = x.CustomerID,
                FirstName = x.FirstName,
                LastName = x.LastName,
                Address1 = x.Addresses.Select(a => a.Address1).SingleOrDefault(),
                Address2 = x.Addresses.Select(a => a.Address2).SingleOrDefault(),
                Phone = x.Addresses.Select(c => c.Contacts.Select(cd => cd.Phone).SingleOrDefault()),
                Fax = x.Addresses.Select(c => c.Contacts.Select(cd => cd.Fax).SingleOrDefault())
            }).ToList();

根据我的情况,单个客户可能有多个地址,但我应该有一个默认的地址。单个地址可能有多个联系人详细信息,但应该有一个我要提取的默认地址。

地址1,地址2,电话和传真都在基本客户类中。我想根据 isdefault 从地址和联系人表中提取单个数据,并填充我的客户。我在 linq 方面不是很好。所以无法撰写查询。请帮我写一下。感谢

2 个答案:

答案 0 :(得分:1)

请尝试以下代码,猜测它可能符合您的要求。

 var bsCustomer1 = db.Customer.Where(p => p.CustomerID == 2)
        .Select(x => new CustomerBase
        {
            CustomerID = x.CustomerID,
            FirstName = x.FirstName,
            LastName = x.LastName,
            Address1 = x.Addresses.First(a => a.IsDefault).Address1,
            Address2 = x.Addresses.First(a => a.IsDefault).Address2,
            Phone = x.Addresses.First(a => a.IsDefault).Contacts.First(c => c.IsDefault).Phone),
            Fax = x.Addresses.First(a => a.IsDefault).Contacts.First(c => c.IsDefault).Fax)
        }).ToList();

答案 1 :(得分:1)

当你说:&#34;我想从地址和联系人表中提取单个数据时,根据isdefault是真实的并且填充我的客户&#34;这可能意味着两件事:

  1. 我想投射一个新对象
  2. 我想更新后备数据库。
  3. 关于EF的一些事情:

    1. 您有一个CRUD(创建,检索,更新,删除)语句的上下文。
    2. 在设置EF文件时,Context知道您在数据库中识别的所有对象。
    3. 为实体上下文和实体名称本身创建t4模板,并在前面的步骤中生成上下文引用,以及创建POCO类对象。
    4. 要创建新对象,您不必引用其上方或下方的对象。您只需要创建它,然后用它来更新数据库。

      因此,对于EF的一个例子,我说我有两个数据库表:

      我有一个表tePerson,它有字段:PersonId,FirstName,LastName,OrderId。此表具有值

      1   Brett   X 1
      2   Emily   X 2
      4   Ryan    Y 1
      10  Mark    Z 1 
      

      OrderId是表teOrder的外键,只有两个字段:OrderId和Description。

      1   Shirt
      2   Dress
      

      我从T4生成的POCO对象是:

      public partial class tePerson
      {
          public int PersonId { get; set; }
          public string FirstName { get; set; }
          public string LastName { get; set; }
          public Nullable<int> OrderId { get; set; }
      
          public virtual teOrder teOrder { get; set; }
      }
      

      重要的是要注意那个虚拟的teOrder&#39;像我这样指向另一个POCO:

      public partial class teOrder
      {
          public teOrder()
          {
              this.tePersons = new HashSet<tePerson>();
          }
      
          public int OrderId { get; set; }
          public string Description { get; set; }
      
          public virtual ICollection<tePerson> tePersons { get; set; }
      }
      

      仅从上下文中投影和更新数据库以及更新下面的数据库的示例。要记住的关键是在做“选择”时的对象。在你做一个类似于ToList()&#39;的方法之前,没有实现EF。使它们具体化否则它们是上下文数据集,你无法链接。

      public class OtherPerson
      {
        public int PersonId { get; set; }
        public string PersonLongName { get; set; }
        public teOrder Order { get; set; }
      }
      
      static void Main(string[] args)
      {
        using (var context = new TesterEntities())
        {
          //Say I just want to project a new object with a select starting from orders and then traversing up.  Not too hard
          var newObjects = context.teOrders.Where(order => order.OrderId == 1)
            //SelectMan will FLATTEN a list off of a parent or child in a one to many relationship
            .SelectMany(peopleInOrderOne => peopleInOrderOne.tePersons)
            .ToList()
            .Select(existingPerson => new OtherPerson
            {
              PersonId = existingPerson.PersonId,
              PersonLongName = $"{existingPerson.FirstName} {existingPerson.LastName}",
              Order = existingPerson.teOrder
            })
            .ToList();
      
          newObjects.ForEach(newPerson => Console.WriteLine($"{newPerson.PersonId} {newPerson.PersonLongName} {newPerson.Order.Description}"));
      
          // Just an action clause to repeat find items in my context, the important thing to note is that y extends teOrder which is another POCO inside my POCO
          Action<string, List<tePerson>> GetOrdersForPeople = (header, people) => 
          {
            Console.WriteLine(header);
            people.ForEach(person => Console.WriteLine($"{person.FirstName} {person.LastName} {person.teOrder.Description}"));
            Console.WriteLine();
          };
      
          //I want to look at a person and their orders.  I don't have to do multiple selects down, lazy loading by default gives me a child object off of EF
          GetOrdersForPeople("First Run", context.tePersons.ToList());
      
      
          //Say I want a new order for a set of persons in my list?
          var newOrder = new teOrder { Description = "Shoes" };
          context.teOrders.Add(newOrder);
          context.SaveChanges();
      
          //Now I want to add the new order
          context.tePersons.SingleOrDefault(person => person.PersonId == 1).teOrder = newOrder;
          context.SaveChanges();
      
          //I want to rexamine now
          GetOrdersForPeople("After changes", context.tePersons.ToList());
      
          //My newOrder is in memory and I can alter it like clay still and the database will know if I change the context
          newOrder.Description = "Athletic Shoes";
          context.SaveChanges();
      
          GetOrdersForPeople("After changes 2", context.tePersons.ToList());
      
          //Say I want to update a few people with new orders at the same time
          var peopleBesidesFirst = context.tePersons.Where(person => person.PersonId != 1).ToList();
          var firstPersonInList = context.tePersons.Where(person => person.PersonId == 1).ToList();
      
          var newOrders = new List<teOrder> {
            new teOrder { Description = "Hat", tePersons = peopleBesidesFirst },
            new teOrder { Description = "Tie", tePersons = firstPersonInList }
            };
      
          context.teOrders.AddRange(newOrders);
          context.SaveChanges();
      
          GetOrdersForPeople("After changes 3", context.tePersons.ToList());
        }
      
        Console.ReadLine();
      }