MSDN > フォーラム ホーム > ADO.NET Entity Framework and LINQ to Entities > Business entity transferred between layers
質問する質問する
 

質問Business entity transferred between layers

  • 2009年7月2日 14:08vmware ユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     コードあり
    Hi

    I am now trying to migrate my knowledge from LINQ to SQL to the Entity Framework.
    One of the main questions I have is the following.

    In my sample code I am using the Northwind database.
    I would like to transfer to the UI a business object which is a customer with the ID 'ALFKI'.
    I would also like to transfer in the same business object all those related 'orders' which happened after 1998-01-01.
    One more important thing is that the UI should only see the ID and contact name for the customer,
    and he/she should only see the shipcity for the orders of the actual customer.

    Below is my try.
    The problem is with it that now the UI can see all fields for the customer, and all fields for the related orders.
    Another problem is that I am not sure whether 'Attach' is the proper method to use and I am not sure whether
    the EF-designer-generated Customer object is which I have to transfer between the app layers.

    Customer customer = null;
    
    using (NorthwindEntities dc = new NorthwindEntities())
    {
       customer =
          (from customers in dc.CustomerSet
           where customers.CustomerID=="ALFKI"
           select customers).FirstOrDefault();
       customer.Orders.Attach(
          from orders in dc.OrderSet
          where 
             orders.OrderDate.HasValue && 
             orders.OrderDate.Value.CompareTo(new DateTime(1998, 1, 1)) > 0 &&
             orders.Customers.CustomerID == "ALFKI"
          select orders);
    }
    
    foreach (Order order in from orders in customer.Orders
                            orderby orders.OrderDate 
                            select orders)
    {
       Console.WriteLine(order.OrderDate.ToString() + " " + order.ShipCity + " " + order.Customers.CustomerID);
    }
    
    Console.ReadLine();
    
    Thanks for any links or code fragments.

すべての返信

  • 2009年7月2日 19:19Ido Flatow. ユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     
    Hi,

    As for getting the Orders, you're code can be changed to:

    orders = customer.Orders.CreateObjectQuery().Where(o=>o.OrderDate != null && o.OrderDate.Value > new DateTime(1998,1,1)).ToList();

    This will extract the orders of the customer which apply to you condition, but will not add them to the Orders collection of the specific customer.

    As for your requirement to see only some of the fields of the entity, this will make you change your query and get an anonymous type:
    var shortDataOfCustomer = (
    from c in dc.CustomerSet 
    where c.CustomerID == "ALFKI"
    select new {c.CustomerID, c.CustomerName}).FirstOrDefault();

    If you want to return Customer objects and not anonymous types, you can change the new {} to new Customer() {CustomerID = c.CustomerID, CustomerName=c.CustomerName}
    of course in this case the entities won't be a part of the ObjectStateManager (meaning the won't be tracked for changes).
               
  • 2009年7月6日 12:58vmware ユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     コードあり
    Thanks for your answer.

    You are right that I could have written the dates comparison simpler - now I corrected this.

    For hiding specifig table fields data from the user I found that I would set the actual entity fields to internal (from public).
    Customer customer = null;
    
    using (NorthwindEntities dc = new NorthwindEntities())
    {
       customer =
          (from customers in dc.CustomerSet
           where customers.CustomerID=="ALFKI"
           select customers).FirstOrDefault();
       customer.Orders.Attach(
          from orders in dc.OrderSet
          where 
             orders.OrderDate > new DateTime(1998, 1, 1)&&
             orders.Customer.CustomerID == "ALFKI"
          select orders);
    }
    
    foreach (Order order in from orders in customer.Orders
                            orderby orders.OrderDate 
                            select orders)
    {
       Console.WriteLine(order.OrderDate.ToString() + " " + order.ShipCity + " " + order.Customer.CustomerID);
    }
    
    Console.ReadLine();<br/>
    

    I still have these two remaining questions:
    1)
    Is Attach the proper method for transferring entities with some specific relations?
    2)
    How can I update data after the UI changes it?
    Updating data only works if the ObjectContext is not disposed.
    But when my business logic component recieves a modified Customer entity from the UI, I couldn't find the proper method to save changes.
    I tried these two (I added the related error messages):
    using (NorthwindEntities dc = new NorthwindEntities())
    {
       dc.AddToCustomerSet(customer);
       dc.SaveChanges();
    }<br/>
    
    The object cannot be added to the ObjectStateManager because it already has an EntityKey. Use ObjectContext.Attach to attach an object that has an existing key.
    using (NorthwindEntities dc = new NorthwindEntities())
    {
       dc.Attach(customer);
       dc.SaveChanges();
    }
    
    An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

    Thanks.