Blog

LINQ to SQL and WCF

This is the scenario… We already have our LINQ DataContext and we need to receive/send info through a WCF service, what can we do to accomplish this?
Option A. - Convert our LINQ entities to data contracts, to do this we just need to modify the Serialization Mode property from None to Unidirectional, right click in any area in the dbml and select properties.
Doing this our LINQ objects are going to have the attributes [DataContract()] and [DataMember] as show in the figure 2. A few questions come to my mind (for sure there are a couple of more and for sure not all the options showed here are going to cover all the cases, hopefully a good part of)… What if we don’t need/want to send all the information in our LINQ objects through the WCF service? Or What if the Service was developed in other department/company and we already have defined the DataContracts?
 
 
 
[Table(Name="dbo.Employees")]
 [DataContract()]
 public partial class Employee : INotifyPropertyChanging, INotifyPropertyChanged
 {
[Column(Storage="_EmployeeID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
  [DataMember(Order=1)]
  public int EmployeeID
  {
   get
   {
    return this._EmployeeID;
   }
   set
   {
    if ((this._EmployeeID != value))
    {
     this.OnEmployeeIDChanging(value);
     this.SendPropertyChanging();
     this._EmployeeID = value;
     this.SendPropertyChanged("EmployeeID");
     this.OnEmployeeIDChanged();
    }
   }
  }
Figure 2
Our Contracts….
   [DataContract]
    public class EmployeeContract : BaseContract
    {
        [DataMember]
        public int EmployeeID { get; set; }
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public string LastName { get; set; }
    }
    [DataContract]
    public class OrderContract : BaseContract
    {
        [DataMember]
        public int OrderID { get; set; }
        [DataMember]
        public string CustomerID { get; set; }
        [DataMember]
        public EmployeeContract Employee { get; set; }
    }
 
 
Option B. - Create a method and manually map DataContract and LINQ objects. In this case an extension method was created.
public static Order ToLinqEntity(this OrderContract contract)
        {
            Order order = new Order()
            {
                OrderID = contract.OrderID,
                CustomerID = contract.CustomerID
            };
            if (null != contract.Employee)
            {
                order.Employee = new Employee()
                {
                    EmployeeID = contract.Employee.EmployeeID,
                    FirstName = contract.Employee.FirstName,
                    LastName = contract.Employee.LastName
                };
            }
            return order;
        }
Option C. - Use Reflection to map DataContract and LINQ objects.
        public static void ToLinqEntity<T>(this BaseContract contract, T entity) where T : class
        {
            if (null == entity)
                throw new ArgumentNullException();
            PropertyInfo[] contractProperties = contract.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo[] entityProperties = entity.GetType().GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
            for (var i = 0; i <= contractProperties.Length - 1; i++)
            {
                //search for the contract property in the property collection of the entity
                PropertyInfo entityPI = (from e in entityProperties
                                         where e.Name == contractProperties[i].Name
                                         select e).FirstOrDefault();
                if (null != entityPI)
                {                   
                    //if the property is a linq association we need to search for the corresponding values
                    if (null != (from ca in entityPI.GetCustomAttributes(true)
                                 where ca.GetType() == typeof(System.Data.Linq.Mapping.AssociationAttribute)
                                 select ca).FirstOrDefault())
                    {
                        //get the value from the contract
                        var contractClass = (BaseContract)contractProperties[i].GetValue(contract, null);
                        //if value isn't null procede to asign to the linq entity
                        if (null != contractClass)
                        {
                            var entityClass = entityPI.GetValue(entity, null);
                            //if class in linq entity==null we need to call the constructor to create a new one
                            if (null == entityClass)
                            {
                                ConstructorInfo ci = entityPI.PropertyType.GetConstructor(new Type[0]);
                                entityClass = ci.Invoke(null);
                            }
                            //recursive call to fill out the new class
                            contractClass.ToLinqEntity(entityClass);
                            //asign value of the new class to the linq entity
                            entityPI.SetValue(entity, entityClass, null);
                        }
                    }
                    else // not a class, we just set the value
                    {
                        entityPI.SetValue(entity, contractProperties[i].GetValue(contract, null), null);
                    }
                } // end null != entityPI
            }//end for contractProperties
        }
 
 

Comments

On 27 Oct 2009 09:57, Justin Broyles said:

Great post!!

On 14 Sep 2010 02:39, Essay Paper said:

thanks for such a great post, it will help me with my college essay writing

On 25 Oct 2010 10:24, lananhhoang2010 said:

Resources like the one you mentioned here will be very useful to me! I will post a link to this page on my blog. I am sure my visitors will find that very useful. Thanks. meilleur placement retraite

On 24 Nov 2010 10:28, cheilitis said:

ye sthanks very much for the helpful info, these types of posts are always the best

On 03 Mar 2011 03:58, Peter Smith said:

Thank you for sharing this useful code. I was looking for this information.

On 08 Mar 2011 04:10, Johnclave said:

I am famalier with SQL but not yet tried with WCF i got to learn many things from this post thanks for sharing this post what is atrial fibrillation

On 15 Jul 2011 04:18, willi said:

WCF is designed for applications in the design and implementation of distributed SOA implementation. WCF is designed for service-oriented architectures, service oriented architecture principles to support distributed computing, where services are available to consumers. Customers can access multiple services and services can be consumed in the number of customers. Create free web page

On 28 Jul 2011 09:22, Anthony said:

I am very new to LINQ and this snippet really helped a lot. Thanks for sharing. I am also reading your other as I may post similar blogs just like yours. One of my favorite blogs is tumescent liposuction san francisco.

Leave a comment

 
 
 
 
CAPTCHA Image Validation