none
code first and wcf - rest in a WebServiceHost RRS feed

  • Question

  • hello,

    I use Entities with navigation properties

        [Serializable()]
        [DataContractAttribute(IsReference = true)]
        public class gDocTest {
            [DataMemberAttribute()]
            public String GP_NATUREPIECEG { get; set; }
            [DataMemberAttribute()]
            public Int32 GP_NUMERO { get; set; }
            [DataMemberAttribute()]
            public String GP_REFINTERNE { get; set; }
            [DataMemberAttribute()]
            public DateTime GP_DATECREATION { get; set; }
    
            [DataMemberAttribute()]
            public String GP_TIERS { get; set; }
    
            [DataMemberAttribute()]
            public virtual gTPTest ThirdParty { get; set; }
        }
    
        [Serializable()]
        [DataContractAttribute(IsReference = true)]
        public class gTPTest {
            public gTPTest () {
                Docs = new List<gDocTest>();
            }
    
            [DataMemberAttribute()]
            public String T_TIERS { get; set; }
            [DataMemberAttribute()]
            public Int32 T_LIBELLE { get; set; }
    
            [DataMemberAttribute()]
            public virtual ICollection<gDocTest> Docs { get; set; }
        }
    
        public class TestContext : DbContext {
            //---------------------------------------------------------------------
            public DbSet<gDocTest> gDocTests { get; set; }
            //---------------------------------------------------------------------
            protected override void OnModelCreating (DbModelBuilder modelBuilder) {
    
                modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    
                modelBuilder.Entity<gTPTest>().ToTable("dbo.TIERS");
                modelBuilder.Entity<gTPTest>().HasKey(p => p.T_TIERS);
    
                modelBuilder.Entity<gDocTest>().ToTable("dbo.PIECE");
                modelBuilder.Entity<gDocTest>().HasKey(p => new { p.GP_NATUREPIECEG, p.GP_NUMERO });
                modelBuilder.Entity<gDocTest>().HasRequired<gTPTest>(d => d.ThirdParty).WithMany(tp => tp.Docs).HasForeignKey(d => d.GP_TIERS);
            }
    
            public TestContext ()
                : base() {
            }
    
            public TestContext (string connectionString)
                : base(connectionString) {
            }
        }
    


    If I comment the navigation properties in the entities and OnModelCreating all is all right.

    With the navigation properties I just have a message, from the explorer, saying that the connection has been reinitialized.

    I think I'm facing a serialization problem, but I don't know where to begin to look. I try to activate the debug in the WebServiceHost but no message, I try to use a DataContractSerializer, the string is empty but I have no error.

    The sample with the edmx file runs OK, But I must use Code First.

    thank you in advance


    thierry
    Saturday, September 3, 2011 5:16 PM

All replies

  •   I have never seen an example of WCF service that was not using
    Linq-2-SQL or EF Models. I don't know about Linq-2-SQL I don't that an
    entity for Linq-2-SQL is an implicit serialized data contract to WCF.
    However, EF entities are an implicit serialized data contact to WCF and
    the entities can me sent and received by a WCF service.
     
     
    Saturday, September 3, 2011 8:27 PM
  • hello,

    and thank you. Ihave now more information. The error is that the returned tyoe does not exactly correspond to the contract type.

    The contract type is gDocument and the returned type is System.Data.Entity.DynamicProxies.gDocument_D60A85A008465912E7B8C4BE24F736DFE607EC93C267F9EE65BC4CEF5B6CE066

    How can I handle this ?

    thank you in advance


    thierry
    Sunday, September 4, 2011 8:07 AM
  • On 9/4/2011 4:07 AM, thierry schmit wrote:
    > hello,
    >
    > and thank you. Ihave now more information. The error is that the
    > returned tyoe does not exactly correspond to the contract type.
    >
    > The contract type is gDocument and the returned type is
    > System.Data.Entity.DynamicProxies.gDocument_D60A85A008465912E7B8C4BE24F736DFE607EC93C267F9EE65BC4CEF5B6CE066
    >
    > How can I handle this ?
    >
    > thank you in advance
     
    I don't know how you can fix it. gDocument must be an object that was
    originated in a different namespace and WCF sees this object as being
    part of System.Data.Entity.DynamicProxies namespace. The namespaces are
    out of sync for the object it seems.
     
    You  may have to do something with WCF KnownTypes.
     
     
    Sunday, September 4, 2011 10:47 AM
  • hello,

    my problem is described here, but I can't apply the attribute to my operation contract.

    I also try by the host.Description.Endpoints => Contract.Operations => operation.Behaviors.

    But no way, I can't have the DataContractResolver to apply !


    thierry
    Sunday, September 4, 2011 8:48 PM
  • On 9/4/2011 4:48 PM, thierry schmit wrote:
    > hello,
    >
    > my problem is described here
    > but I can't apply the attribute to my operation contract.
    >
    > I also try by the host.Description.Endpoints => Contract.Operations =>
    > operation.Behaviors.
    >
    > But no way, I can't have the DataContractResolver to apply !
    >
     
    In the link you provided, I suggest that you find out what is happening
    there.
     
    <Copied>
     
    The ProxyDataContractResolver
     
    A DataContractResolver has two methods that map types and names during
    the serialization process. During serialization,
    .NET types are mapped to type names that are part of the serialization
    payload. This is done in the “TryResolveType” method.
    The code below includes the implementation of the ProxyDataContractResolver.
    The TryResolveType method determines if the entity’s type is a proxy or not,
    and if it is a proxy uses the non-proxy type name in the payload:
     
    <end>
     
    Sunday, September 4, 2011 9:07 PM
  • I would like to... but I actually can't force my service based on WebServiceHost to use this serializer !
    thierry
    Sunday, September 4, 2011 9:13 PM
  • one solution is :

    tc.Configuration.ProxyCreationEnabled = false;
    tc.Configuration.LazyLoadingEnabled = false;
    

    but, how to force a DataContractResolver !!


    thierry
    Sunday, September 4, 2011 9:23 PM
  • On 9/4/2011 5:13 PM, thierry schmit wrote:
    > I would like to... but I actually can't force my service based on
    > WebServiceHost to use this serializer !
     
    If it were me doing this, I would just take the easy way out and use the
    Model first approach, since an EF entity is an implicit serialized
    datacontract to WCF that can be passed with ease.
     
    Sunday, September 4, 2011 9:26 PM
  • I agree but... the database still exists (with 2300 tables) and comprises no constraint or even pk... that causes some trouble when generating the edmx file.
    thierry
    Sunday, September 4, 2011 9:34 PM
  • Hello,

    Regarding serializing POCO proxies with WCF, this was a good practice like your provided one. http://msdn.microsoft.com/en-us/library/ee705457.aspx

    In addition, i think the best description about splitting a large edmx into multiple ones was provided on ADO.NET team blog.

    http://blogs.msdn.com/b/adonet/archive/2008/11/24/working-with-large-models-in-entity-framework-part-1.aspx

    http://blogs.msdn.com/b/adonet/archive/2008/11/25/working-with-large-models-in-entity-framework-part-2.aspx

    Hope this helps.

    Thanks,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, September 5, 2011 8:22 AM
  • hello,

    I hardly try.... but still no way to get the custom data contract applying ???

    In the contract interface:

    [ServiceContract(Namespace = "http://lcs-cegid-documents.fr/2011/09/03",
                     Name = "ProductsSales")] 
        public interface IProductsSales {
            ....
        }
    

    I have

            [OperationContract]
            [MsdnApplyDataContractResolver]
            [WebGet(UriTemplate = "GDocs/{gDocNature}/{gDocNum}")]
            [Description("Returns the details of an order")]
            gDocument GetOrder (string gDocNature, string gDocNum);
    

    Where MsdnApplyDataContractResolver is the Attribute from your link.

    In the implementation of the contract :

        public class ProductsSales : IProductsSales {
            #region IProductsSales Membres
    
            public gDocument GetOrder (string gDocNature, string gDocNum) {
                gDocument gDoc = null;
    
                //gDoc = new gDocument { GP_NATUREPIECEG = "CC", GP_NUMERO = 1, GP_REFINTERNE = "ref interne"};
                int inum = Int32.Parse(gDocNum);
                try {
                    using ( CegidContext tc = new CegidContext(ConfigurationManager.ConnectionStrings["CegidContext"].ConnectionString) ) {
                        //tc.Configuration.ProxyCreationEnabled = false;
                        tc.Configuration.LazyLoadingEnabled = false;
                        gDoc = ( from order in tc.gDocuments 
                                  where order.GP_NATUREPIECEG == gDocNature && order.GP_NUMERO == inum
                                  orderby order.GP_DATECREATION
                                  select order).FirstOrDefault();
                    }
                } catch ( Exception ex ) {
                    Console.WriteLine(ex.Message);
                    throw new WebFaultException(HttpStatusCode.BadRequest);
                }
    
                return gDoc;
            }
    
            ....
            #endregion
        }
    

    I still have the serialization exception, except if I uncomment tc.Configuration.ProxyCreationEnabled = false;

    Just in case, the hosting code is :

    namespace ProductsSalesHost {
        class Program {
            static void Main (string[] args) {
                try {
                    WebServiceHost host = new WebServiceHost(
                        typeof(ProductsSalesService.ProductsSales));
                    
                    /*foreach ( ServiceEndpoint endpoint in host.Description.Endpoints ) {
                        foreach ( OperationDescription operation in endpoint.Contract.Operations ) {
                            DataContractSerializerOperationBehavior behavior =
                                    operation.Behaviors.Find<DataContractSerializerOperationBehavior>();
                            //behavior.DataContractResolver = new ProductsSalesService.CustomResolver();
                            behavior.DataContractResolver = new ProxyDataContractResolver();
    
                            //behavior.IgnoreExtensionDataObject = true;
                        }
                    }*/
    
                    host.Open();
                    Console.WriteLine("Service running");
                    Console.WriteLine("Press ENTER to stop the service");
                    Console.ReadLine();
                    host.Close();
                } catch (System.ServiceModel.AddressAccessDeniedException aade) {
                    Console.WriteLine(aade.Message);
                    Console.WriteLine("\r\nUse:");
                    Console.WriteLine("netsh http add urlacl url=http://+:*****/ user=UserName\r\nWhere ***** is the port number, see app.config");
                } catch ( Exception ex ) {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }
    



    thierry
    Monday, September 5, 2011 2:42 PM
  • On 9/5/2011 4:22 AM, Larcolais Gong wrote:
    > Hello,
    >
    > Regarding serializing POCO proxies with WCF, this was a good practice
    > like your provided one.
    >
    > In addition, i think the best description about splitting a large edmx
    > into multiple ones was provided on ADO.NET team blog.
    >
    >
    >
    >
     
    What EF needs is a way to do the Model first and being able to generate
    the entities with no primary keys, no associations period, and let the
    developer do things his or herself. That way the model is generated. The
    entities can be sent through WCF with no problems since an EF entity in
    the model first approach is an implicit serialized datacontract and
    known type to WCF.
     
    Why should one go through all this nonsense with Code First, just
    because the VS IDE can't create the model without primary keys on a
    table? Make the model first approach just generate the entities without
    primary keys and associations - a vanilla model.
     
    Monday, September 5, 2011 11:37 PM
  •  
    The other thing you can do is use serializable Data Transfer Object
    mapping the POCO to  the DTO and sending The DTO through the WCF service
    to the client and sent the DTO back to the service where it would be
    mapped back to your POCO to persist it.
     
    You may not want to hear it, but that is an option. I always use DTO(s)
    and I would leave the POCO behind on the service side -- that's what I
    do with the EF entities even though I could have sent the entities
    through WCF. I use DTO(s) in n-tier solutions using EF and the DAL is
    behind WCF.
     
    Monday, September 5, 2011 11:51 PM
  • about DTO...

    yes but: SQL server (dataset) -> Entities (POCO / proxy) -> DTO -> serialization -> WS message, that's a very long trip in cpu and memory terms, isn't it ?

    If I count well that makes 5 versions of the same data in memory and most of the cpu time spent in data adaptation, no ?


    thierry
    Tuesday, September 6, 2011 3:22 PM