5

मैं 3 टेबल है (कई रिश्ते के लिए कई)निम्नलिखित फ़्लुएंट एनएचबेर्नेट मैपिंग में क्या गलत है?

  1. संसाधन {RESOURCEID, विवरण}
  2. भूमिका {भूमिका-आईडी, विवरण}
  3. अनुमति {RESOURCEID, भूमिका-आईडी}

मैं कर रहा हूँ Flent-nHibernate में उपरोक्त तालिकाओं को मानचित्र करने का प्रयास कर रहा है। यही वह है जो मैं करने की कोशिश कर रहा हूं।

var aResource = session.Get<Resource>(1); // 2 Roles associated (Role 1 and 2) 
var aRole = session.Get<Role>(1); 
aResource.Remove(aRole); // I try to delete just 1 role from permission. 

लेकिन यहाँ उत्पन्न एसक्यूएल है (जो गलत है)

Delete from Permission where ResourceId = 1 
Insert into Permission (ResourceId, RoleId) values (1, 2); 

के बजाय (सही तरीके से)

Delete from Permission where ResourceId = 1 and RoleId = 1 

क्यों nHibernate इस तरह व्यवहार करते हैं? मैपिंग के साथ क्या गलत है? मैंने आईलीस्ट के बजाय सेट के साथ भी कोशिश की। यहां पूरा कोड है।

संस्थाओं

public class Resource 
{ 
    public virtual string Description { get; set; } 
    public virtual int ResourceId { get; set; } 
    public virtual IList<Role> Roles { get; set; } 

    public Resource() 
    { 
     Roles = new List<Role>(); 
    } 
} 

public class Role 
{ 
    public virtual string Description { get; set; } 
    public virtual int RoleId { get; set; } 
    public virtual IList<Resource> Resources { get; set; } 

    public Role() 
    { 
     Resources = new List<Resource>(); 
    } 
} 

मानचित्रण यहाँ

// Mapping .. 
public class ResourceMap : ClassMap<Resource> 
{ 
    public ResourceMap() 
    { 
     Id(x => x.ResourceId); 
     Map(x => x.Description); 
     HasManyToMany(x => x.Roles).Table("Permission"); 
    } 
} 

public class RoleMap : ClassMap<Role> 
{ 
    public RoleMap() 
    { 
     Id(x => x.RoleId); 
     Map(x => x.Description); 
     HasManyToMany(x => x.Resources).Table("Permission"); 
    } 
} 

कार्यक्रम

static void Main(string[] args) 
    { 
     var factory = CreateSessionFactory(); 
     using (var session = factory.OpenSession()) 
     { 
      using (var tran = session.BeginTransaction()) 
      { 
       var aResource = session.Get<Resource>(1); 
       var aRole = session.Get<Role>(1); 
       aResource.Remove(aRole); 
       session.Save(a); 
       session.Flush(); 
       tran.Commit(); 
      } 
     } 
    } 
    private static ISessionFactory CreateSessionFactory() 
    { 
     return Fluently.Configure() 
      .Database(MsSqlConfiguration.MsSql2008 
      .ConnectionString("server=(local);database=Store;Integrated Security=SSPI")) 
      .Mappings(m => 
       m.FluentMappings.AddFromAssemblyOf<Program>() 
       .Conventions.Add<CustomForeignKeyConvention>()) 
      .BuildSessionFactory(); 
    } 

    public class CustomForeignKeyConvention : ForeignKeyConvention 
    { 
     protected override string GetKeyName(FluentNHibernate.Member property, Type type) 
     { 
      return property == null ? type.Name + "Id" : property.Name + "Id"; 
     } 
    } 

धन्यवाद, अशरफ।

उत्तर

6

nHibernate सोचता है कि जब तक आप माता-पिता/बच्चे की घोषणा नहीं करते हैं, तब तक सभी संबंध द्वि-दिशात्मक होते हैं। इसलिए आपको "उलटा" चाहिए। इसके बिना, नए मान के साथ "हटाएं" और "मनोरंजन" के रूप में दो कदम उठाए जाते हैं, खासकर "बैग" प्रकार (डिफ़ॉल्ट)। ManyToMany के लिए, बदलते इकाई संग्रह प्रकार (हैशसेट/सेट) "बैग" के मानचित्रण को प्रभावित नहीं करेगा। यह केवल हैसमनी के लिए काम करता है। आपको विशेष रूप से मानचित्र में "AsSet" कहने की आवश्यकता है। (IList/ICollection) मानचित्र "बैग" के लिए। यदि आप सूची चाहते हैं, तो आपको मानचित्र में "AsList" रखना होगा। लेकिन सूची में तालिका में अतिरिक्त इंडेक्स कॉलम की आवश्यकता है।

// Mapping .. 
public class ResourceMap : ClassMap<Resource> 
{ 
    public ResourceMap() 
    { 
     Id(x => x.ResourceId); 
     Map(x => x.Description); 
     HasManyToMany(x => x.Roles).AsSet().Inverse().Table("Permission"); 
    } 
} 

public class RoleMap : ClassMap<Role> 
{ 
    public RoleMap() 
    { 
     Id(x => x.RoleId); 
     Map(x => x.Description); 
     HasManyToMany(x => x.Resources).AsSet().Cascade.SaveUpdate().Table("Permission"); 
    } 
} 

इसके अलावा, मैं Fetch.Select()। LazyLoad() lazyload के लिए।

+0

बिल्कुल सही। धन्यवाद स्टोटो। चूंकि मैं अपनी प्राथमिक इकाई के रूप में संसाधन का उपयोग कर रहा हूं। मुझे कई मैपिंग में कई को फ्लिप करने की ज़रूरत है। ResourceeMap में । HasManyToMany (x => x.Roles) .sset()। Cascade.SaveUpdate() तालिका ("अनुमति"); रोलमैप में । HasManyToMany (x => x.Resources) .sset()। उलटा() तालिका ("अनुमति"); – ashraf

+0

इसके अलावा कोई भी इसके बारे में ब्लॉग करता है। http://www.codinginstinct.com/2010/03/nhibernate-tip-use-set-for-many-to-many.html – ashraf

संबंधित मुद्दे