EF with POCO + WCF + WPF. Reuse POCO classes on cl

2019-02-11 00:53发布

问题:

We are developing a 3-tier application with a WPF client, which communicates through WCF with the BLL. We use EF to access our database. We have been using the default EntityObject code generator of EF, but had lots of problems and serialization issues when sending those object through the wire, and when processing and reattaching them in the BLL.

We are about to switch to the POCO template, and rewrite the data access and the communication parts of our app (we are hoping to have a cleaner architecture and less "magic code" that way.

My question is whether it is a good idea to reuse the POCO classes on the client side? Or should we create separate DTO classes? Even if they would be identical to the POCO entity classes? What are the pros/cons of the two approaches?

回答1:

Definitely use DTOs + AutoMapper. Otherwise you'll have tons of problems with DataContractSerializer while using WCF due to circular dependencies (especially problematic with navigational properties). Even though you may omit DTOs initially, you'll be forced to used them later on due to problems mentioned above. So I would advice using proper DTOs for each tier.

Also your tier specific models will carry different attributes. You may also need to modify (i.e. specialize) the data that you carry up in each tier. So if your project is large enough (or have the prospect to be so), use DTOs with proper naming and place them in proper locations (i.e. not all in the same assembly).



回答2:

Now i work on similar issue. I have done next:

  1. Create next assemplities:

SF.Contracts - that just defined ServiceCotnracts and DataContracts. Obvious all datacontracts may be used like POCO classes in EF (but i dont use t4 or other generator - all POCO classes and DataContext are written manualy, because i need to use very bad database). SF.

SF.DataAccessObjects - in this assemlity i implement my edmx and DataContext. SF.Services - implementation of WCF Services.

So, a large numbers of select WCF method have next signature and implementation:

        public List<Vulner> VulnerSelect(int[] idList = null, string[] navigationPropertiesList = null)
    {
        var query = from vulner in _businessModel.DataModel.VulnerSet
                    select vulner;

        if (navigationPropertiesList != null)
            navigationPropertiesList.Select(p =>{query = ((ObjectQuery<Vulner>)query).Include(p);
                                   return true; });
        if (idList != null)
            query = query.Where(p => idList.Contains(p.Id));

        return query.ToList();
    }

and you can use this method like this:

WCFproxy.VulnerSelect(new[]{1,2,3},new[]{"SecurityObjects", "SecurityObjrcts.Problem"});

so that, you have no problem with serrialization, navigation properties etc. and you can clearly indicate which NavigationProperties must be load.

p.s.: sory for my bad English :)



回答3:

I'd say use DTOs.

Circular dependencies and large object graphs can be a serious problem causing either errors or far too much serialised traffic. There's just way too much noise on an ORM controlled object to send it down the line.

I use a service layer to access my domain objects and use LINQ extensively, but I always return DTO objects back to the client.