2010-01-27 3 views
5

Không chắc chắn nếu tiêu đề có ý nghĩa, nhưng đây là những gì tôi đang làm. Tôi đang sử dụng AutoMapper để ánh xạ Entity Framework Entities của tôi cho các đối tượng DTO của tôi và ngược lại. Sự cố xảy ra khi tôi cố gắng ánh xạ dữ liệu DTO tới thực thể EF. Không có thuộc tính để ánh xạ thuộc tính cho EntityKey. Để khắc phục điều này, tôi làm một số như sau:Có cách nào chung để sử dụng ValueResolver của AutoMapper để ánh xạ các giá trị EntityKey cho các thực thể EF?

 Mapper.CreateMap<VideoDTO, Video>() 
      .ForMember(dest => dest.EntityKey, opt => 
opt.ResolveUsing<VideoEntityKeyResolver>()); 

Lớp VideoEntityKeyResolver trông giống như:

public class VideoEntityKeyResolver : ValueResolver<VideoDTO, EntityKey> 
{ 
    protected override EntityKey ResolveCore(VideoDTO source) 
    { 
     EntityKey key = new EntityKey("EntityFrameworkTestingEntities.Videos", 
      "VideoId", source.VideoId); 
     return key; 
    } 
} 

tôi đã tự hỏi nếu có một cách chung chung hơn để làm điều này mà tôi có thể có 1 lớp với một hàm tạo lấy Tên bộ thực thể, Tên thuộc tính khóa và Giá trị khóa trong một hàm tạo. Tôi đã nghĩ đến việc chỉ thêm một thuộc tính EntityKey vào các đối tượng DTO của tôi, âm thanh rất giống như băng qua các luồng khi toàn bộ điểm tạo đối tượng DTO là làm thắt chặt lớp dữ liệu của tôi trong phần còn lại của ứng dụng của tôi .

Trên ghi chú hoàn toàn không liên quan (tôi có thể tạo câu hỏi mới nếu cần), nơi tôi cần xác định ánh xạ chính xác khi sử dụng AutoMapper? Hiện tại tôi đang thực hiện nó trong constructor của đối tượng context (đối tượng kho lưu trữ EF của tôi), nhưng tôi tin nó khá tốn kém và không chính xác, nó hoạt động.

Trả lời

8

tôi đã không đi xa như vậy để kiểm tra điều này, nhưng sau đây nên làm việc:

public class EntityKeyResolver<T, TProperty> : ValueResolver<T, EntityKey> where T : class 
{ 
    private Expression<Func<T, TProperty>> _propertyExpression; 
    private string _qualifiedEntitySetName; 
    private string _keyName; 

    public EntityKeyResolver(string qualifiedEntitySetName, string keyName, Expression<Func<T, TProperty>> propertyExpression) 
    { 
     _qualifiedEntitySetName = qualifiedEntitySetName; 
     _keyName = keyName; 
     _propertyExpression = propertyExpression; 
    } 

    protected override EntityKey ResolveCore(T source) 
    { 
     return new EntityKey(_qualifiedEntitySetName, _keyName, ExpressionHelper.GetValue(_propertyExpression)); 
    } 
} 

Các ExpressionHelper là một lớp tĩnh mà tôi sử dụng để giúp đánh giá biểu thức trong một loạt các trường hợp. Phương pháp GetValue trông như thế này:

internal static TProperty GetValue<T, TProperty>(T obj, Expression<Func<T, TProperty>> expression) where T : class 
{ 
    if (obj == null) 
    { 
     return default(TProperty); 
    } 

    Func<T, TProperty> func = expression.Compile(); 

    return func(obj); 
} 

Sau đó bạn sẽ làm thay đổi mã của bạn như sau (giả sử VideoId là một Guid):

Mapper.CreateMap<VideoDTO, Video>()   
      .ForMember(dest => dest.EntityKey, opt => opt.ResolveUsing(new EntityKeyResolver<VideoDTO, Guid>("EntityFrameworkTestingEntities.Videos", "VideoId", v => v.VideoId))); 

Có lẽ một chút dài dòng hơn bạn muốn. Một thay thế cho resolver chung sẽ được sử dụng để lập bản đồ MapFrom phím thực thể (họ là về bình đẳng verbose):

Mapper.CreateMap<VideoDTO, Video>()   
       .ForMember(dest => dest.EntityKey, opt => opt.MapFrom(src => new EntityKey("EntityFrameworkTestingEntities.Videos", "VideoId", src.VideoId))); 

Đối với câu hỏi khác của bạn, tôi đã nhận được trong thói quen của việc tạo ra một lớp tĩnh khởi tạo các bản đồ của tôi và đặt một boolean là có hay không ánh xạ đã được tạo ra vì bạn chỉ cần gọi nó một lần cho mỗi AppDomain. Sau đó, trong hàm tạo của kho lưu trữ của tôi, tôi chỉ cần gọi MapInitializer.EnsureMaps();

+0

Cảm ơn phản hồi chi tiết. Hầu hết nó là trên đầu của tôi, nhưng đó là nhiều hơn tôi hơn bạn. Tôi vẫn vật lộn với việc sử dụng lambda và như vậy. Nhưng dù sao, bạn có biết liệu có phương pháp tự động hóa cho phép bạn chỉ định rõ ràng giá trị được tính cho một thuộc tính không? Nếu đó là trường hợp, tôi chỉ có thể tạo một đối tượng EntityKey với các tham số cần thiết và ánh xạ giá trị đó cho thuộc tính EntityKey trên thực thể của tôi. Tôi đã nhìn vào phương pháp MapFrom AutoMapper, nhưng chưa có thời gian để nghiên cứu nó. – jason

+0

Tôi sẽ đề xuất rằng đó là một phương pháp đơn giản hơn, nhưng đã quyết định trả lời trực tiếp câu hỏi của bạn. Tôi sẽ thêm nó vào câu trả lời. (Ngoài ra, đừng quên bỏ phiếu và/hoặc chấp nhận câu trả lời nếu bạn tìm thấy nó để đáp ứng nhu cầu của bạn) – mkedobbs

+0

Cảm ơn bạn đã đi xa hơn và xa hơn về câu hỏi này. Điều này thực sự đã giúp tôi! Tôi đã đi trước và giải quyết trên bản đồ chỉ đến một tài sản EntityKey và dường như đã làm việc. – jason