2009-09-01 27 views
5

Tôi đang cố gắng tìm ra cách ánh xạ một thuộc tính IDictionary trong thông thạo 1.0 RTM.Mã thông thạo để ánh xạ IDictionary <SomeEntity, int>?

Từ sự hiểu biết của tôi, điều này chuyển thành liên kết ba năm.

Ví dụ:

class Bar 
{ 
    public IDictionary<SomeEntity, int> Foo {get; set;} 
} 

Bar.hbm.xml sau đó sẽ chứa:

<map name="Foo" table="BarFooTable"> 
    <key column="..."/> 
    <index-many-to-many class="SomeEntity" column="SomeEntity_Id"/> 
    <element column="Value" type="int"/> 
</map> 

tôi sẽ có gì để viết trong nhibernate thạo để tạo ra bản đồ xml này?

Điểm quan tâm ở đây là khóa là loại thực thể trong khi giá trị là một loại giá trị. (sửa đổi: Ít nhất, điều này dường như để phân biệt chính nó từ các ví dụ khác nhau và câu hỏi nổi xung quanh trên stackoverflow hoặc nhóm google, đó là giá trị giá trị hoặc khóa-key)

Sau nhiều thử nghiệm tôi có thể tạo bản đồ cho một IDictionary<SomeEntity,SomeEntity> (các loại thực thể tinh khiết):

HasManyToMany(x => x.Foo) 
     .AsMap("Key") 
     .AsTernaryAssociation("Key2", "Value") 
     ; 

tôi cũng có thể tạo ra một bản đồ cho một (kiểu giá trị tinh khiết) IDictionary<int,int>:

HasMany(x => x.Foo) 
    .AsMap<int>("Key") 
    .Element("Value") 
    ; 

tôi thậm chí có thể nhận được một số cách để tạo ra một bản đồ cho một IDictionary<int, SomeValue), mặc dù không có NHibernate nào sẽ chấp nhận.

Nhưng tôi không thể tìm ra cách tạo bản đồ cho IDictionary<SomeValue, int> đó là những gì tôi muốn. Ai đó có thể cung cấp một số lời khuyên?

+0

crossposted để http://groups.google.com/group/fluent-nhibernate/browse_thread/thread/b1b335ff5f9a6a40 – fostandy

Trả lời

1

Tôi chạy vào cùng một vấn đề, và không phải là' t hài lòng với việc trộn các bản đồ thông thạo và hbm. Bạn có thể thấy bản sửa lỗi của tôi here.

0

Có vẻ như chúng ta có cùng một vấn đề:

How to map this in Fluent.NHibernate

Tôi chỉ hbm.xml sử dụng (được tạo ra bởi Fluent.Nhibernate trong dự án của tôi) tôi sửa đổi nó một chút oufcourse. Nếu bạn đặt

.Mappings(m => 
    {            
     m.FluentMappings.AddFromAssemblyOf<DomainClass>() 
         .ExportTo("Path"); 
     m.HbmMappings.AddFromAssemblyOf<DomainClass>(); 
    }) 

và nếu bạn có cả ClassMap và hbm.xml các hbm.xml nên ghi đè ClassMap, vì vậy bạn sẽ bị phạt cho đến khi nó được cố định.

Tôi cũng cần tự nhiên-id cho lớp học của tôi và nó cũng không được hỗ trợ với Fluent.Nhibernate, vì vậy tôi đã không có lựa chọn nào khác để sử dụng hbm.xml

+0

Yeah, đây hiện là con đường tôi làm mọi việc. Thật không may tôi có một lớp khá nặng, trong khi nó có rất nhiều thuộc tính có thể được ánh xạ với thông thạo, cũng có một IDictionary . "Giải pháp" của tôi cho đến nay là tách các chức năng thành các lớp riêng biệt (một bản đồ lưu loát, một thông qua hbm.xml thô) và sử dụng ánh xạ một-một, nhưng vì lý do hiệu suất, bây giờ nó không thể loại bỏ sự tham gia/thêm lựa chọn xảy ra từ này. (xem http://groups.google.com/group/fluent-nhibernate/browse_frm/thread/b5fe376e257436e9/35d9cf5cef4303d0) – fostandy

2
HasMany(x => x.Foo) 
    .KeyColumn("BarId") 
    .Element("IntValue") 
    .AsMap<SomeEntity>("SomeEntityId") 
    .AsTernaryAssociation("SomeEntityId"); 
+0

Chỉ có cùng một vấn đề, dựa trên giải pháp của bạn, tôi đã kết thúc với 'HasManyToMany (x => x. Bộ sưu tập) \t \t \t \t .ParentKeyColumn ("ParentId") \t \t \t \t .ChildKeyColumn ("ChildId") \t \t \t \t .AsMap ("ChildId"). Element ("Giá trị", p => p .Column ("Giá trị"). Loại ()) \t \t \t \t .AsTernaryAssociation ("ChildId", "Giá trị") \t \t \t \t \t \t \t \t .table ("Relationstable"); ' –

0

Với những (giản thể) lớp:

class LetterTemplate 
{ 
    IDictionary<State, FieldAccessOptionality> StateAccess {get; protected set;} 
} 

class State 
{ 
} 

enum FieldAccessOptionality 
{ 
} 

này đã làm việc cho tôi.

(Có, tôi biết giá trị là Enum, nhưng nguyên tắc cũng giống như một int).

HasManyToMany(x => x.StateAccess) 
    .ParentKeyColumn("`letter_template`") 
    .ChildKeyColumn("`state`") 
    .AsMap<State>("`state`") 
    .Element("`access`", 
     p => 
     p.Type<IntEnumType<FieldAccessOptionality>>()) 
    .AsTernaryAssociation("`state`", "`access`") 
    .Table("`letter_template_state_access`"); 

Lưu ý lớp IntEnumType <> chuyển đổi từ enum thành int cho NHibernate. Nếu bạn đã ánh xạ một int thay vì một enum, bạn chỉ có thể sử dụng tiêu chuẩn NHibernate Int32Type IUserType. Việc niêm yết đầy đủ cho lớp này là như sau:

public class IntEnumType<T> : IUserType where T : struct 
{ 
    public object Assemble(object cached, object owner) 
    { 
    return cached; 
    } 

    public object DeepCopy(object value) 
    { 
    return value; 
    } 

    public object Disassemble(object value) 
    { 
    return value; 
    } 

    public new bool Equals(object a, object b) 
    { 
    return Object.Equals(a, b); 
    } 

    public int GetHashCode(object x) 
    { 
    if (x == null) 
     return 0; 
    else 
     return x.GetHashCode(); 
    } 

    public bool IsMutable 
    { 
    get { return false; } 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
    object result = NHibernateUtil.Int32.NullSafeGet(rs, names); 
    if (result == null) 
    { 
     return null; 
    } 
    else 
    { 
     Type typ = Enum.GetUnderlyingType(typeof(T)); 
     result = Convert.ChangeType(result, typ); 
     return Enum.ToObject(typeof(T), result); 
    } 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
    if (value == null) 
     ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value; 
    else 
     ((IDataParameter)cmd.Parameters[index]).Value = Convert.ChangeType(value, typeof(int)); 
    } 

    public object Replace(object original, object target, object owner) 
    { 
    return original; 
    } 

    public Type ReturnedType 
    { 
    get { return typeof(T); } 
    } 

    public SqlType[] SqlTypes 
    { 
    get 
    { 
     SqlType type = new SqlType(DbType.Int32); 
     return new SqlType[] { type }; 
    } 
    } 

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