简体   繁体   中英

Best Practices for Integrating AutoMapper with WCF Data Services and EF4

We are exposing a domain model via WCF Data Services. The model originates from EF4, and requires some additional work to get it into the required form for being published via the web-service.

I'd like to handle this outside of EF4, to keep our EDMX focused on the model rather than it's usage. My idea is to create a customized "ServiceModel" which is specifically for the web-service and contains the service-specific concerns.

My question is in how to best wire-up automapper in the middle of WCF Data Services. I'm using WCF Data Services with a custom (reflection-based) provider for the ServiceModels. Where can I convert the OData query (for ServiceModels) into an EF4 query (for DomainModels), and map the results back to ServiceModels?

I use Automapper in my WCF Services to map from database entities to data contracts. For each service I create a static AutomapBootstrap class with a method to InitializeMap. Then for each service, I decorate the service with an AutomapServiceBehavior attribute.

I do not know if this will work for your scenario because WCF Data Services is a little different from vanilla WCF SOAP services and services using WCF WebBindings.

However, its worth a look.

This is the Service Behavior

[CoverageExclude(Reason.Framework)]
public sealed class AutomapServiceBehavior : Attribute, IServiceBehavior
{
    public AutomapServiceBehavior()
    {
    }

    #region IServiceBehavior Members

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, 
        Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
        AutomapBootstrap.InitializeMap();
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
    }

    public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
    {
    }

    #endregion
}

This is my mapper

public class AutomapBootstrap
{
    public static void InitializeMap()
    {
        Mapper.CreateMap<CreateBookmarkRequest, TagsToSaveRequest>()
            .ForMember(dest => dest.TagsToSave, opt => opt.MapFrom(src => src.BookmarkTags))
            .ForMember(dest => dest.SystemObjectId, opt => opt.UseValue((int)SystemObjectType.Bookmark))
            .ForMember(dest => dest.SystemObjectRecordId, opt => opt.Ignore());

    }
}

this is how I wire up my service to automap

[AutomapServiceBehavior]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Clouds : ICloudService
{ 
    // service operation implementation details elided
}

Final note, my service is a vanilla WCF Service using the WebBinding and serving up data in a REST style fashion.

Unless your domain model is very simple and very shallow (very few collections within it) I would suggest against projecting off of your domain objects to build your service (DTO) layer.

Rather, I would project your DTOs directly off of your data store (DB). Failure to do so will result in many SELECT N+1 issues and will end up being more expensive to maintain than simply hydrating your DTOs directly from your database tables.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM