Handling Many to Many in Entity Framework 4.0

Recently, I have had some questions on setting up "Many to Many" while using a layered software model with EF4.0 using POCO objects. Hopefully this post helps clarify how to handle the database integration while preserving the business domain model and reducing code. In layered code I use the following components.

 

Service contracts - Contract that a service implements

Services – objects that define functionality for a domain entity

Business Managers – objects that define custom business logic for a service

Data Servers – objects that define what will be pushed and pulled from a data source

Entities – objects that mimic data source objects or tables

Factories – objects that utilize one or more services for building categorized functionality

 

Out of the above objects, the two that are customized the most are the Data Server and Entities but each component is generated for each table within a database. The Data Server changes are driven by business requirements for data interaction with the database. POCO entity changes are driven to close gaps between business entities and the business process. This usually consists of changing single objects to composite objects, but depending on the business goals code for "many to many" objects can be minimized or omitted entirely. So how do we do this? Take a look at the following example and let's go step by step...

 

Below is a Customer table and AddressLocation table. Because of the many to many relationship I created the CustomerDropShipment table so a customer can have many AddressLocations that can be used as dropshipments for online purchases. When working with without Entity Framework, I would generate the above layers for all three tables, but with Entity Framework I only have to generate the layers for Customer and AddressLocation and generate the additional POCO object CustomerDropshipment and add the scaler property, "CustomerDropLocations". You will also notice the "DropShipments" collection was added as well We add these to make it easier and more natural for creating and retrieving the dropshipments for a customer. 

 

 

 

 

 

Next, lets look at the code that handles all of this. The below code is a natural way based on the current business domain for adding multiple dropshipments for an existing customer.

public void CreateCustomerDropShipment()

{

   try

   {

      Customer existCustomer = new Customer() { CustomerId = 37 };      existCustomer.DropShipments.Add(new CustomerDropShipment()

      {

         DropShipmentLocation =
new AddressLocation()

         {

            Address = "5434 Dropshipment Way 2",           

            City = "Dropshipmentville2",           

            LocationName = "Dropshipment 2",

            StateId = 1,

            Zip = "54345-08"

         }

      });

      existCustomer.DropShipments.Add(
new CustomerDropShipment()

      {

         DropShipmentLocation =
new AddressLocation()

         {

            Address =
"5434 Dropshipment Way 3",

            City = "Dropshipmentville3",           

            LocationName =
"Dropshipment 3",

            StateId = 1,

            Zip = "54345-09"

         }

      });

      var ret = Customer.Core.Factories.CustomerMgt.AddCustomerDropShipments(existCustomer);

   }

   catch (Exception ex)

   {

      throw ex;

   }

}

The magic behind the scene for processing the dropshipments is simplified as well

public bool AddDropShipments(Customer objCustomer)

{

   bool retSuccess = false;

   try

   {

      using (CustomerEntities db = new CustomerEntities())

      {

         var modCustomer =

            (from c in db.Customers

            where c.CustomerId == objCustomer.CustomerIdselect c).SingleOrDefault();

 

         if (modCustomer != null)

         {

            modCustomer.DropShipments = objCustomer.DropShipments;

         }

         db.SaveChanges();

         retSuccess =
true;

      }

   }

   catch (Exception ex)

   {

      throw ex;

   }

   return retSuccess;

}

Because the Customer scaler property DropShipments is of type CustomerDropShipment and we added the scaler property "DropShipmentLocation" we can get one or all of the dropshipment locations for a customer too.

public CustomerDropShipment GetCustomerDropshipment(CustomerDropShipment objDropShipment)

{

   CustomerDropShipment DropShipment = null;

   try

   {

      using (CustomerEntities db = new CustomerEntities())

      {

         var retDrop =

         (from d in db.CustomerDropShipments

         from l in db.AddressLocations         where d.LocationId == l.LocationId

         && d.CustomerId == objDropShipment.CustomerId

         && d.LocationId == objDropShipment.LocationId

         select new { d, l }).SingleOrDefault();         if (retDrop != null)

         {

            DropShipment =
new CustomerDropShipment() { CustomerId = retDrop.d.CustomerId};

            DropShipment.DropShipmentLocation = retDrop.d.DropShipmentLocation;

         }

         return DropShipment;

      }

   }

   catch (Exception ex)

   {

      throw ex;

   }

}

public Customer GetCustomerDropshipments(int CustomerId)

{

   Customer objCustomer = null;

   try

   {

      using (CustomerEntities db = new CustomerEntities())

      {

         var retDrops =

         from d in db.CustomerDropShipments

         join l in db.AddressLocations on

         d.LocationId equals l.LocationId

         where d.CustomerId == CustomerId

         select new { d, l };         objCustomer =

new Customer() { CustomerId = CustomerId };         foreach (var drop in retDrops)

         {

            var dropshipment = drop.d;

            dropshipment.DropShipmentLocation = drop.l;

            objCustomer.DropShipments.Add(dropshipment);

         }

         return objCustomer;

      }

   }

   catch (Exception ex)

   {

      throw ex;

   }

}

So in short using Entity Framework 4.0 can reduce code for layers that normally would generated by handling the modeling for relationships in this case, between Customer and AddressLocation tables through the DropShipmentLocation scaler property.

Currently rated 1.5 by 4 people

  • Currently 1.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5