Làm thế nào để bạn ánh xạ một enum dưới dạng giá trị int với NHibernate thông thạo?


88

Câu hỏi nói lên tất cả thực sự, mặc định là nó để lập bản đồ stringnhưng tôi cần nó để lập bản đồ int.

Tôi hiện đang sử dụng PersistenceModelđể thiết lập các quy ước của mình nếu điều đó tạo ra bất kỳ sự khác biệt nào. Cảm ơn trước.

Cập nhật Nhận thấy rằng việc truy cập vào phiên bản mới nhất của mã từ thân cây đã giải quyết được tai ương của tôi.


5
nếu bạn tự giải quyết vấn đề, bạn nên trả lời nó, sau đó đánh dấu nó là câu trả lời đúng để những người tìm kiếm trong tương lai sẽ tìm thấy nó.
Jeff Martin

Bạn có thể vui lòng đăng câu trả lời được không?
mxmissile

Xong rồi các bạn. Xin lỗi về sự chậm trễ. Tôi thực sự không chắc mình phải làm gì với một câu hỏi không phải là câu hỏi vì tôi chỉ cần phiên bản mới nhất của các thư viện.
Garry Shutler

2
Thức ăn cho bot google: Tôi đã nhận được "quyền truy cập bất hợp pháp để tải bộ sưu tập" trước khi triển khai điều này cho ánh xạ enum của mình.
4imble

Câu trả lời:


84

Cách xác định quy ước này đôi khi đã thay đổi trước đây, bây giờ là:

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

4
Đây là câu trả lời chính xác cho các phiên bản mới nhất gần đây của nhibernate thạo
Sean Chambers

Băng. ^^ Sean đã nói gì.
Martin Suchanek

1
Điều này có vẻ như nó hoạt động tốt cho tất cả các loại enum, nhưng nếu bạn muốn một số dưới dạng chuỗi và một số dưới dạng int? Tôi nghĩ điều này có thể được định cấu hình ở cấp ánh xạ thuộc tính.
UpTheCreek

4
Xem câu trả lời của @SztupY bên dưới để mở rộng điều này để cho phép các enums có thể vô hiệu hóa. stackoverflow.com/questions/439003/…
Jon Adams

45

Vì vậy, như đã đề cập, việc lấy phiên bản Fluent NHibernate mới nhất ra khỏi cốp xe đã đưa tôi đến nơi tôi cần đến. Một ví dụ về ánh xạ cho một enum với mã mới nhất là:

Map(quote => quote.Status).CustomTypeIs(typeof(QuoteStatus));

Kiểu tùy chỉnh buộc nó phải được xử lý như một thể hiện của enum thay vì sử dụng GenericEnumMapper<TEnum> .

Tôi thực sự đang xem xét việc gửi một bản vá để có thể thay đổi giữa một trình ánh xạ enum tồn tại một chuỗi và một trình liên kết duy trì một int vì có vẻ như một thứ mà bạn có thể đặt làm quy ước.


Điều này xuất hiện trên hoạt động gần đây của tôi và mọi thứ đã thay đổi trong các phiên bản mới hơn của Fluent NHibernate để làm cho việc này dễ dàng hơn.

Để làm cho tất cả các enum được ánh xạ dưới dạng số nguyên, bây giờ bạn có thể tạo một quy ước như sau:

public class EnumConvention : IUserTypeConvention
{
    public bool Accept(IProperty target)
    {
        return target.PropertyType.IsEnum;
    }

    public void Apply(IProperty target)
    {
        target.CustomTypeIs(target.PropertyType);
    }

    public bool Accept(Type type)
    {
        return type.IsEnum;
    }
}

Sau đó, ánh xạ của bạn chỉ phải là:

Map(quote => quote.Status);

Bạn thêm quy ước vào ánh xạ Fluent NHibernate của mình như vậy;

Fluently.Configure(nHibConfig)
    .Mappings(mappingConfiguration =>
    {
        mappingConfiguration.FluentMappings
            .ConventionDiscovery.AddFromAssemblyOf<EnumConvention>();
    })
    ./* other configuration */

3
với "int mode" làm mặc định. Ai kiên trì enums như một chuỗi ?!
Andrew Bullock

4
Có thể là một cơ sở dữ liệu di sản với giá trị chuỗi đã có trong đó
Chris Haines

4
+1 gai góc. @ Andrew Bullock: câu trả lời cho câu hỏi của bạn: bất kỳ ai xử lý cơ sở dữ liệu thế giới thực.
Sky Sanders

Có giao diện IProperty nào trong FN không?
Tien Do

40

Đừng quên về nullable enums (like ExampleEnum? ExampleProperty)! Chúng cần được kiểm tra riêng. Đây là cách nó được thực hiện với cấu hình kiểu FNH mới:

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum ||
            (x.Property.PropertyType.IsGenericType && 
             x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
             x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
            );
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

4
+1 cho phần bổ sung này! Phiên bản đầu tiên không hoạt động đối với enums nullable (chúng vẫn ở dạng chuỗi).
longda

@SztupY Loại cột trong cơ sở dữ liệu là int? Và khi loại chấp nhận Cờ? Giống như:MyEnum.Active | MyEnum.Paused
ridermansb

@RidermandeSousaBarbosa: Đối với cờ, hãy kiểm tra ở đây: stackoverflow.com/questions/2805661/…
SztupY

25

đây là cách tôi đã ánh xạ một thuộc tính enum với một giá trị int:

Map(x => x.Status).CustomType(typeof(Int32));

làm việc cho tôi!


2
Cảm ơn cho việc cung cấp câu trả lời đơn giản nhất
Mike

Nỗi lo duy nhất của tôi với điều này là bạn phải nhớ áp dụng nó cho mọi enum. Đó là những gì các quy ước được tạo ra.
Garry Shutler

Điều này hoạt động để đọc nhưng không thành công khi tôi thử truy vấn tiêu chí. Mặc dù vậy, tôi đã thử thiết lập một quy ước (xem câu trả lời cho câu hỏi này).
Thomas Bratt

Tôi nghĩ nó rất tuyệt - nhưng điều này sẽ gây ra vấn đề: hãy xem bài đăng này. nhforge.org/blogs/nhibernate/archive/2008/10/20/…
UpTheCreek

@UpTheCreek Có vẻ như điều này đã được khắc phục và hiện được James Gregory từ nhóm NH đề xuất: mail-archive.com/fluent-nhibernate@googlegroups.com/…
Ilya Kogan

1

Đối với những người sử dụng Fluent NHibernate với Automapping (và có thể là vùng chứa IoC):

Đây IUserTypeConventionlà câu trả lời của @ Julien ở trên: https://stackoverflow.com/a/1706462/878612

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

Cấu hình Fluent NHibernate Automapping có thể được định cấu hình như sau:

    protected virtual ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(SetupDatabase)
            .Mappings(mappingConfiguration =>
                {
                    mappingConfiguration.AutoMappings
                        .Add(CreateAutomappings);
                }
            ).BuildSessionFactory();
    }

    protected virtual IPersistenceConfigurer SetupDatabase()
    {
        return MsSqlConfiguration.MsSql2008.UseOuterJoin()
        .ConnectionString(x => 
             x.FromConnectionStringWithKey("AppDatabase")) // In Web.config
        .ShowSql();
    }

    protected static AutoPersistenceModel CreateAutomappings()
    {
        return AutoMap.AssemblyOf<ClassInAnAssemblyToBeMapped>(
            new EntityAutomapConfiguration())
            .Conventions.Setup(c =>
                {
                    // Other IUserTypeConvention classes here
                    c.Add<EnumConvention>();
                });
    }

* Sau đó, CreateSessionFactorycó thể được sử dụng trong IoC như Castle Windsor (sử dụng PersistenceFacility và trình cài đặt) một cách dễ dàng. *

    Kernel.Register(
        Component.For<ISessionFactory>()
            .UsingFactoryMethod(() => CreateSessionFactory()),
            Component.For<ISession>()
            .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
            .LifestylePerWebRequest() 
    );

0

Bạn có thể tạo một NHibernate IUserTypevà chỉ định nó bằng cách sử dụng CustomTypeIs<T>()trên bản đồ tài sản.


0

Bạn nên giữ các giá trị dưới dạng int / tinyint trong Bảng DB của mình. Để ánh xạ enum của bạn, bạn cần chỉ định ánh xạ chính xác. Vui lòng xem bản đồ và mẫu enum dưới đây,

Lớp lập bản đồ

bản đồ lớp công khai: Giao dịch bản đồ lớp
{
    Bản đồ giao dịch công khai ()
    {
        // Các ánh xạ khác
        .....
        // Ánh xạ cho enum
        Bản đồ (x => x.Status, "Trạng thái"). CustomType ();

        Bảng ("Giao dịch");
    }
}

Enum

public enum TransactionStatus
{
   Đang chờ = 1,
   Đã xử lý = 2,
   RolledBack = 3,
   Bị chặn = 4,
   Đã hoàn lại = 5,
   Đã xử lý = 6,
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.