2010-04-13 27 views
5

Trong việc tìm kiếm của tôi cho một bộ lọc cơ sở dữ liệu phiên bản toàn cho một ứng dụng, tôi đã viết đoạn mã sau là gì:cách tốt nhất để cung cấp một AutoMappingOverride cho một giao diện trong automapper fluentnhibernate

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using FluentNHibernate.Automapping; 
using FluentNHibernate.Automapping.Alterations; 
using FluentNHibernate.Mapping; 
using MvcExtensions.Model; 
using NHibernate; 

namespace MvcExtensions.Services.Impl.FluentNHibernate 
{ 
    public interface IVersionAware 
    { 
     string Version { get; set; } 
    } 

    public class VersionFilter : FilterDefinition 
    { 
     const string FILTERNAME = "MyVersionFilter"; 
     const string COLUMNNAME = "Version"; 

     public VersionFilter() 
     { 
      this.WithName(FILTERNAME) 
       .WithCondition("Version = :"+COLUMNNAME) 
       .AddParameter(COLUMNNAME, NHibernateUtil.String); 
     } 

     public static void EnableVersionFilter(ISession session,string version) 
     { 
      session.EnableFilter(FILTERNAME).SetParameter(COLUMNNAME, version); 
     } 

     public static void DisableVersionFilter(ISession session) 
     { 
      session.DisableFilter(FILTERNAME); 
     } 
    } 

    public class VersionAwareOverride : IAutoMappingOverride<IVersionAware> 
    { 
     #region IAutoMappingOverride<IVersionAware> Members 

     public void Override(AutoMapping<IVersionAware> mapping) 
     { 
      mapping.ApplyFilter<VersionFilter>(); 
     } 
     #endregion 
    } 

} 

Nhưng, kể từ khi ghi đè không hoạt động trên các giao diện, tôi đang tìm cách để thực hiện điều này. Hiện nay tôi đang sử dụng theo cách này (chứ không cồng kềnh) cho mỗi lớp mà thực hiện giao diện:

public class SomeVersionedEntity : IModelId, IVersionAware 
{ 
    public virtual int Id { get; set; } 
    public virtual string Version { get; set; } 
} 

public class SomeVersionedEntityOverride : IAutoMappingOverride<SomeVersionedEntity> 
{ 
    #region IAutoMappingOverride<SomeVersionedEntity> Members 

    public void Override(AutoMapping<SomeVersionedEntity> mapping) 
    { 
     mapping.ApplyFilter<VersionFilter>(); 
    } 

    #endregion 
} 

Tôi đã được nhìn IClassmap giao diện vv, nhưng họ dường như không cung cấp một cách tiếp cận phương pháp ApplyFilter , vì vậy tôi không có một đầu mối ở đây ...

Vì tôi có lẽ không phải là người đầu tiên có vấn đề này, tôi khá chắc chắn rằng nó sẽ là có thể; Tôi chỉ không khá chắc chắn cách làm việc này ..

EDIT: Tôi đã nhận được một chút gần gũi hơn với một giải pháp chung:

Đây là cách tôi đã cố gắng để giải quyết nó:

Sử dụng một lớp tổng quát để thực hiện thay đổi đến các lớp học thực hiện một giao diện:

public abstract class AutomappingInterfaceAlteration<I> : IAutoMappingAlteration 
{ 
    public void Alter(AutoPersistenceModel model) 
    { 
     model.OverrideAll(map => 
     { 
      var recordType = map.GetType().GetGenericArguments().Single(); 
      if (typeof(I).IsAssignableFrom(recordType)) 
      { 
       this.GetType().GetMethod("overrideStuff").MakeGenericMethod(recordType).Invoke(this, new object[] { model }); 
      } 
     }); 
    } 

    public void overrideStuff<T>(AutoPersistenceModel pm) where T : I 
    { 
     pm.Override<T>(a => Override(a)); 
    } 

    public abstract void Override<T>(AutoMapping<T> am) where T:I; 
} 

Và một thực hiện cụ thể:

01.235.
public class VersionAwareAlteration : AutomappingInterfaceAlteration<IVersionAware> 
{ 
    public override void Override<T>(AutoMapping<T> am) 
    { 
     am.Map(x => x.Version).Column("VersionTest"); 
     am.ApplyFilter<VersionFilter>(); 
    } 
} 

Đáng tiếc là tôi nhận được lỗi sau bây giờ:

[InvalidOperationException: Collection was modified; enumeration operation may not execute.] 
    System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) +51 
    System.Collections.Generic.Enumerator.MoveNextRare() +7661017 
    System.Collections.Generic.Enumerator.MoveNext() +61 
    System.Linq.WhereListIterator`1.MoveNext() +156 
    FluentNHibernate.Utils.CollectionExtensions.Each(IEnumerable`1 enumerable, Action`1 each) +239 
    FluentNHibernate.Automapping.AutoMapper.ApplyOverrides(Type classType, IList`1 mappedProperties, ClassMappingBase mapping) +345 
    FluentNHibernate.Automapping.AutoMapper.MergeMap(Type classType, ClassMappingBase mapping, IList`1 mappedProperties) +43 
    FluentNHibernate.Automapping.AutoMapper.Map(Type classType, List`1 types) +566 
    FluentNHibernate.Automapping.AutoPersistenceModel.AddMapping(Type type) +85 
    FluentNHibernate.Automapping.AutoPersistenceModel.CompileMappings() +746 

EDIT 2: Tôi quản lý để có được một chút nữa; bây giờ tôi gọi "Override" sử dụng phản chiếu cho mỗi lớp mà thực hiện giao diện:

public abstract class PersistenceOverride<I> 
{ 

    public void DoOverrides(AutoPersistenceModel model,IEnumerable<Type> Mytypes) 
    { 
     foreach(var t in Mytypes.Where(x=>typeof(I).IsAssignableFrom(x))) 
      ManualOverride(t,model); 
    } 

    private void ManualOverride(Type recordType,AutoPersistenceModel model) 
    { 
     var t_amt = typeof(AutoMapping<>).MakeGenericType(recordType); 
     var t_act = typeof(Action<>).MakeGenericType(t_amt); 
     var m = typeof(PersistenceOverride<I>) 
       .GetMethod("MyOverride") 
       .MakeGenericMethod(recordType) 
       .Invoke(this, null); 
     model.GetType().GetMethod("Override").MakeGenericMethod(recordType).Invoke(model, new object[] { m }); 
    } 

    public abstract Action<AutoMapping<T>> MyOverride<T>() where T:I; 
} 

public class VersionAwareOverride : PersistenceOverride<IVersionAware> 
{ 
    public override Action<AutoMapping<T>> MyOverride<T>() 
    { 
     return am => 
     { 
      am.Map(x => x.Version).Column(VersionFilter.COLUMNNAME); 
      am.ApplyFilter<VersionFilter>(); 
     }; 
    } 
} 

Tuy nhiên, vì một lý do này hay cách khác tôi tạo ra các file hbm không chứa bất kỳ "lọc" các lĩnh vực .... Có lẽ ai đó có thể giúp tôi thêm một chút bây giờ không ??

Trả lời

1

Rõ ràng, đã xảy ra lỗi trong phiên bản hiện tại của thông thạo-nhibernate. Các bộ lọc không được sao chép khi bạn sử dụng Automapper.Override <T>.

Tôi đã chia nhỏ nguồn, sửa lỗi, thử nghiệm và bây giờ tôi đã gửi yêu cầu kéo tới những người thông thạo trên github.

Còn bây giờ, bạn có thể tải về mã nguồn cố định tại http://github.com/ToJans/fluent-nhibernate/commit/29058de9b2bc3af85bc433aa6f71549f7b5d8e04

tại Ngoài ra còn có một bài đăng blog đầy đủ về cách để làm điều này: http://www.corebvba.be/blog/post/How-to-override-interface-mappings-and-creata-a-generic-entity-version-filter-in-fluent-nhibernate.aspx

Các vấn đề liên quan