流利Nhibernate:试图用复合键创建实体,也是两个引用的关键 [英] Fluent Nhibernate: Trying to create entity with composite key that is also the keys for two references

查看:170
本文介绍了流利Nhibernate:试图用复合键创建实体,也是两个引用的关键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

引用是单向的。此实体的表(StoreProduct)实际上是一个具有以下字段的连接表:


$ b $ ul
Store_id
  • Product_id

  • ExtraBit



  • 所以我使用了一个化合物ID(store_id和($ product_id),ExtraBit只是一个字符串:

    pre $ public $ StoreProduct

    protected StoreProduct :this(null,null,null){}
    public StoreProduct(Store c_Store,Product c_Product,String c_ExtraBit)
    {
    Store = c_Store;
    Product = c_Product;
    ExtraBit = c_ExtraBit;
    }
    public virtual int Product_id {get;组; }
    public virtual int Store_id {get;组; }
    public virtual Store Store {get;组; }
    public virtual Product Product {get;组; }
    public virtual String ExtraBit {get;组; }

    $ b public override int GetHashCode()
    {
    return Store.GetHashCode()+ Product.GetHashCode();
    }

    public override bool Equals(object obj)
    {
    StoreProduct obj_StoreProduct;
    obj_StoreProduct = obj as StoreProduct;
    if(obj_StoreProduct == null)
    {
    return false;

    if(obj_StoreProduct.Product!= this.Product&& obj_StoreProduct.Store!= this.Store)
    {
    return false;
    }
    返回true;


    $ b b

    和映射:

      public class Order_DetailMap:ClassMap< StoreProduct> 
    {
    public Order_DetailMap()
    {
    表(StoreProduct);
    LazyLoad();
    CompositeId().KeyProperty(x => x.Store_id).KeyProperty(x => x.Product_id);
    引用(x => x.Store).ForeignKey(Store_id)。Cascade.All();
    引用(x => x.Product).ForeignKey(Product_id)。Cascade.All();
    Map(x => x.ExtraBit);


    code


    我尝试保存StoreProduct及其新创建的商店和产品。谁能帮忙?这里有一些输出:

     未处理的异常:System.ArgumentOutOfRangeException:索引超出范围。 
    必须是非负数,小于集合的大小。
    参数名称:index $ b $在System.ThrowHelper.ThrowArgumentOutOfRangeException()
    在System.Data.SQLite.SQLiteParameterCollection.GetParameter(Int32索引)$ b $在System.Data.Common.DbParameterCollection .System.Collections.IList.get_Item
    (Int32 index)$ b $在NHibernate.Type.Int32Type.Set(IDbCommand rs,Object value,Int32 index)in
    d:\CSharp\NH \NH\\\
    hibernate\src\NHibernate\Type\Int32Type.cs:第60行$ NHibernate.Type.NullableType.NullSafeSet(IDbCommand cmd,对象值,$ $ b $ 32索引)在d:\CSharp\NH\NH\\\
    hibernate\src\NHibernate\Type\NullableType.cs:行
    180
    在NHibernate.Type.NullableType.NullSafeSet(IDbCommand st,Object value,Int3
    2 index,ISessionImplementor session)在d:\CSharp\NH\NH\\\
    hibernate\src\NHiberna
    te\Type\NullableType.cs :行NHibernate.Type.ComponentType.NullSafe 139
    Set(IDbCommand st,Object value,Int
    32 begin,ISessionImplementor session)在d:\CSharp\NH\NH\\\
    hibernate\src\NHibern
    ate\Type\ ComponentType.cs:行221
    在NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(对象ID,O
    bject []字段,对象rowId,布尔值[] includeProperty,布尔值[] [] includeColu
    mns,Int32表,IDbCommand语句,ISessionImplementor会话,Int32索引
    )在d:\CSharp\NH\NH\\\
    hibernate\src\NHibernate\Persister\Entity\AbstractEntityPe
    rsister.cs:第2418行






    编辑:感谢以下帮助,我似乎有一个体面的解决方案:
    $ b 商店映射和类:

      namespace compoundIDtest.Domain.Mappings 
    {
    public class StoreMap:ClassMap< Store>
    {
    public StoreMap()
    {
    Id(x => x.Id).Column(Store_id);
    Map(x => x.Name);
    HasMany(x => x.Staff)
    .Inverse()
    .Cascade.All();
    HasManyToMany(x => x.Products)
    .Cascade.All()
    .Table(StoreProduct);




    $ b namespace compoundIDtest.Domain.Entities
    {
    public class Store
    {
    public virtual int Id {get;私人设置}
    public virtual string Name {get;组; }
    公共虚拟IList<产品>产品{get;组; }
    公共虚拟IList<员工>工作人员{get;组; }
    公共虚拟IList< StoreProduct> StoreProducts {get;组; }
    $ b $ public Store()
    {
    Products = new List< Product>();
    Staff = new List< Employee>();


    public virtual void AddProduct(Product product)
    {
    product.StoresStockedIn.Add(this);
    Products.Add(product);
    }

    public virtual void AddEmployee(Employee employee)
    {
    employee.Store = this;
    Staff.Add(employee);


    public override int GetHashCode()
    {
    return Name.GetHashCode();


    public override bool Equals(object obj)
    {
    Store obj_Store;
    obj_Store = obj作为商店;
    if(obj_Store == null)
    {
    return false;

    if(obj_Store.Name!= this.Name)
    {
    return false;
    }
    返回true;
    }



    $ b}
    }

    产品映射和类

      namespace compoundIDtest.Domain。映射
    {
    public class ProductMap:ClassMap< Product>
    {
    public ProductMap()
    {
    Id(x => x.Id).Column(Product_id);
    Map(x => x.Name);
    Map(x => x.Price);
    HasManyToMany(x => x.StoresStockedIn)
    .Cascade.All()
    .Inverse()
    .Table(StoreProduct);




    $ b namespace compoundIDtest.Domain.Entities
    {
    public class Product
    {
    public virtual int Id {get;私人设置}
    public virtual string Name {get;组; }
    public virtual double Price {get;组; }
    公共虚拟IList< Store> StoresStockedIn {get;组; }
    公共虚拟IList< StoreProduct> StoreProducts {get;组; }
    public Product()
    {
    StoresStockedIn = new List< Store>();
    StoreProducts =新列表< StoreProduct>();


    $ b public override int GetHashCode()
    {
    return Name.GetHashCode();


    public override bool Equals(object obj)
    {
    Product obj_Product;
    obj_Product = obj as Product;
    if(obj_Product == null)
    {
    return false;

    if(obj_Product.Name!= this.Name)
    {
    return false;
    }
    返回true;







    和StoreProduct

      namespace compoundIDtest.Domain.Mappings 
    {
    公共类Order_DetailMap:ClassMap< StoreProduct>
    {
    public Order_DetailMap()
    {
    表(StoreProduct);
    LazyLoad();
    CompositeId()。KeyReference(x => x.Store,Store_id)。KeyReference(x => x.Product,Product_id);
    引用(x => x.Store,Store_id)。Not.Update()。Not.Insert()。Cascade.All();
    引用(x => x.Product,Product_id)。Not.Update()。Not.Insert()。Cascade.All();
    Map(x => x.ExtraBit);




    $ b namespace compoundIDtest.Domain.Entities
    {
    public class StoreProduct
    {
    public StoreProduct(){}

    public virtual Store Store {get;组; }
    public virtual Product Product {get;组; }
    public virtual String ExtraBit {get;组; }
    $ b public override int GetHashCode()
    {
    $ b $ if(this.ExtraBit!= null)
    {
    return Store.GetHashCode ()+ Product.GetHashCode()+ ExtraBit.GetHashCode();
    }

    return Store.GetHashCode()+ Product.GetHashCode();


    $ b public override bool Equals(object obj)
    {
    StoreProduct obj_StoreProduct;
    obj_StoreProduct = obj as StoreProduct;
    if(obj_StoreProduct == null)
    {
    return false;

    if(obj_StoreProduct.Product!= this.Product&& obj_StoreProduct.Store!= this.Store&& obj_StoreProduct.ExtraBit!= this.ExtraBit)
    {
    返回false;
    }
    返回true;





    $ b $ p $强>这里是一个应用程序的代码来测试以上内容:

      using System; 
    使用System.IO;
    使用compoundIDtest.Domain.Entities;
    使用FluentNHibernate.Cfg;
    使用FluentNHibernate.Cfg.Db;
    使用NHibernate;
    使用NHibernate.Cfg;
    使用NHibernate.Tool.hbm2ddl;
    使用FluentNHibernate.Conventions;


    namespace compoundIDtest
    {
    class Program
    {
    private const string DbFile =firstProgram.db;

    static void Main()
    {
    //创建我们的NHibernate会话工厂
    var sessionFactory = CreateSessionFactory();

    使用(var session = sessionFactory.OpenSession())
    {
    //使用(var transaction = session.BeginTransaction())$ b填充数据库
    $ b {
    //创建几个商店,每个商店都有一些产品和员工
    var barginBasin = new Store {Name =Bargin Basin};
    var superMart = new Store {Name =SuperMart};
    var CornerShop = new Store {Name =Corner Shop};


    var potatoes = new Product {Name =Potatoes,Price = 3.60};
    var fish = new Product {Name =Fish,Price = 4.49};
    var milk = new Product {Name =Milk,Price = 0.79};
    var bread = new Product {Name =Bread,Price = 1.29};
    var cheese = new Product {Name =Cheese,Price = 2.10};
    var waffles = new Product {Name =Waffles,Price = 2.41};
    var poison = new Product {Name =Poison,Price = 1.50};


    var daisy = new Employee {FirstName =Daisy,LastName =Harrison};
    var jack = new Employee {FirstName =Jack,LastName =Torrance};
    var sue = new Employee {FirstName =Sue,LastName =Walkters};
    var bill = new Employee {FirstName =Bill,LastName =Taft};
    var joan = new Employee {FirstName =Joan,LastName =Pope};

    var storeproduct = new StoreProduct {Store = CornerShop,Product = poison,ExtraBit =Extra Bit};

    //session.SaveOrUpdate(CornerShop);
    //session.SaveOrUpdate(poison);

    session.Save(storeproduct);


    //将商品添加到商店中,每个
    商店中的商品都有一些交叉,因为商品关系是多对多
    AddProductsToStore(barginBasin,土豆,鱼,牛奶,面包,奶酪);
    AddProductsToStore(superMart,bread,cheese,waffles);

    //将员工添加到商店,这种关系是一对多的,所以一个
    //员工一次只能在一个商店工作
    AddEmployeesToStore( barginBasin,daisy,jack,sue);
    AddEmployeesToStore(superMart,bill,joan);

    //保存两个商店,这通过级联
    session.SaveOrUpdate(barginBasin);
    session.SaveOrUpdate(superMart);
    //session.SaveOrUpdate(CornerShop);
    //session.SaveOrUpdate(poison);
    //session.SaveOrUpdate(store product);

    transaction.Commit();



    $ b使用(var session = sessionFactory.OpenSession())
    {
    // retreive all stores and display them
    using(var transaction = session.BeginTransaction())
    {
    var products = session.CreateCriteria(typeof(Product))
    .List< Product>();

    foreach(var product in products)
    {
    product.Price = 100;
    session.SaveOrUpdate(product);




    $ b var storeproducts = session.CreateCriteria(typeof(StoreProduct))。List< StoreProduct>();


    foreach(StoreProduct storeproduct in storeproducts)
    {

    if(storeproduct.Store.Name ==SuperMart)
    {
    storeproduct.ExtraBit =谢谢,再来;
    }

    session.SaveOrUpdate(storeproduct);



    transaction.Commit();





    $ b Console.ReadKey();


    private static ISessionFactory CreateSessionFactory()
    {
    return Fluentfully.Configure()
    .Database(SQLiteConfiguration.Standard
    .UsingFile (DbFile))
    .Mappings(m =>
    m.FluentMappings.AddFromAssemblyOf< Program>())
    .ExposeConfiguration(BuildSchema)
    .BuildSessionFactory()


    private static void BuildSchema(Configuration config)
    {
    //删除每次运行的现有数据库
    if(File.Exists(DbFile ))
    File.Delete(DbFile);

    //这个NHibernate工具需要一个配置(映射信息在)
    //并从中导出一个数据库模式
    新的SchemaExport(config)
    .Create (假,真);


    private static void WriteStorePretty(Store store)
    {
    Console.WriteLine(store.Name);
    Console.WriteLine(Products:);

    foreach(var product in store.Products)
    {
    Console.WriteLine(+ product.Name);
    }

    Console.WriteLine(Staff:);

    foreach(var storeStaff中的雇员)
    {
    Console.WriteLine(+ employee.FirstName ++ employee.LastName);
    }

    Console.WriteLine();


    public static void AddProductsToStore(store store,params Product [] products)
    {
    foreach(var product in products)
    {
    store.AddProduct(product);



    public static void AddEmployeesToStore(Store store,params Employee [] employees)
    {
    foreach(var employee in employees)
    {
    store.AddEmployee(employee);



    $ b $ / code $ / pre

    解决方案

    我有一个映射几乎完全相同,我最终映射它是这样的:

      public class Order_DetailMap:ClassMap< StoreProduct> 
    {
    public Order_DetailMap()
    {
    表(StoreProduct);
    CompositeId()
    .KeyReference(x => x.Store,Store_id)
    .KeyReference(x => x.Product,Product_id);

    Map(x => x.ExtraBit);




    $ Store Product 类我添加和删除方法使得这个中间类的创建几乎看不见。示例如下:

      public class Store 
    {
    public IList< StoreProduct> StoreProducts {get;组; }

    //其他属性和构造函数

    public virtual void AddProduct(Product productToAdd,string extraBit)
    StoreProduct newStoreProduct = new StoreProduct ,productToAdd,extraBit);
    storeProducts.Add(newStoreProduct);




    $ b $ p
    $ b除了上面的内容,在我的 Store Product 类中设置了code> StoreProduct
    Cascade.AllDeleteOrphan()



    我从未能够映射 StoreProduct 这样,当它自己保存时,它会创建一个新的 Store 和一个新的 Product >。我不得不像上面那样映射它。因此,在您实际创建关系之前,您的 Store Product 将需要存在( StoreProduct ),这取决于你是从哪个方面创建新的 StoreProduct

    编辑:



    您也可以像这样映射以达到您想要的效果:

      public class Order_DetailMap:ClassMap< StoreProduct> 
    {
    public Order_DetailMap()
    {
    表(StoreProduct);
    CompositeId()
    .KeyReference(x => x.Store,Store_id)
    .KeyReference(x => x.Product,Product_id);

    引用(x => x.Store,Store_id)
    .Not.Update()
    .Not.Insert()
    .Cascade.All ();

    引用(x => x.Product,Product_id)
    .Not.Update()
    .Not.Insert()
    .Cascade.All ();

    Map(x => x.ExtraBit);
    }
    }


    The references are unidirectional. The table (StoreProduct) for this entity is actually a join table that has these fields:

    • Store_id
    • Product_id
    • ExtraBit

    So I went with an entity having a compoundID (store_id and product_id) and the ExtraBit is just a string:

    public class StoreProduct
    {
        protected StoreProduct():this(null,null,null){ }
        public StoreProduct(Store c_Store, Product c_Product, String c_ExtraBit)
        {
            Store = c_Store;
            Product = c_Product;
            ExtraBit = c_ExtraBit;
        } 
        public virtual int Product_id { get; set; }
        public virtual int Store_id { get; set; }
        public virtual Store Store { get; set; }
        public virtual Product Product { get; set; }
        public virtual String ExtraBit { get; set; }
    
    
        public override int GetHashCode()
        {
            return Store.GetHashCode() + Product.GetHashCode();
        }
    
        public override bool Equals(object obj)
        {
            StoreProduct obj_StoreProduct;
            obj_StoreProduct = obj as StoreProduct;
            if (obj_StoreProduct == null)
            {
                return false;
            }
            if (obj_StoreProduct.Product != this.Product && obj_StoreProduct.Store != this.Store)
            {
                return false;
            }
            return true;
        }
    
    }
    

    And the mapping:

    public class Order_DetailMap : ClassMap<StoreProduct>
    {
        public Order_DetailMap()
        {
            Table("StoreProduct");
            LazyLoad();
            CompositeId().KeyProperty(x => x.Store_id).KeyProperty(x => x.Product_id);
            References(x => x.Store).ForeignKey("Store_id").Cascade.All();
            References(x => x.Product).ForeignKey("Product_id").Cascade.All();
            Map(x => x.ExtraBit);
        }
    }
    

    It doesn't work though, when I tried saving the StoreProduct and its newly created Store and product. Can anyone help? Here is some output:

     Unhandled Exception: System.ArgumentOutOfRangeException: Index was out of range.
     Must be non-negative and less than the size of the collection.
    Parameter name: index
       at System.ThrowHelper.ThrowArgumentOutOfRangeException()
       at System.Data.SQLite.SQLiteParameterCollection.GetParameter(Int32 index)
       at System.Data.Common.DbParameterCollection.System.Collections.IList.get_Item
    (Int32 index)
       at NHibernate.Type.Int32Type.Set(IDbCommand rs, Object value, Int32 index) in
     d:\CSharp\NH\NH\nhibernate\src\NHibernate\Type\Int32Type.cs:line 60
       at NHibernate.Type.NullableType.NullSafeSet(IDbCommand cmd, Object value, Int
    32 index) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Type\NullableType.cs:line
     180
       at NHibernate.Type.NullableType.NullSafeSet(IDbCommand st, Object value, Int3
    2 index, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHiberna
    te\Type\NullableType.cs:line 139
       at NHibernate.Type.ComponentType.NullSafeSet(IDbCommand st, Object value, Int
    32 begin, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibern
    ate\Type\ComponentType.cs:line 221
       at NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object id, O
    bject[] fields, Object rowId, Boolean[] includeProperty, Boolean[][] includeColu
    mns, Int32 table, IDbCommand statement, ISessionImplementor session, Int32 index
    ) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPe
    rsister.cs:line 2418
    


    Edit: Thanks to the help bellow I seem to have a decent solution:

    Store Mapping and Class:

    namespace compoundIDtest.Domain.Mappings
    {
        public class StoreMap : ClassMap<Store>
        {
            public StoreMap()
            {
                Id(x => x.Id).Column("Store_id");
                Map(x => x.Name);
                HasMany(x => x.Staff)
                  .Inverse()
                  .Cascade.All();
                HasManyToMany(x => x.Products)
                 .Cascade.All()
                 .Table("StoreProduct");
            }
        }
    }
    
    
    namespace compoundIDtest.Domain.Entities
    {
        public class Store
        {
            public virtual int Id { get; private set; }
            public virtual string Name { get; set; }
            public virtual IList<Product> Products { get; set; }
            public virtual IList<Employee> Staff { get; set; }
            public virtual IList<StoreProduct> StoreProducts { get; set; }
    
            public Store()
            {
                Products = new List<Product>();
                Staff = new List<Employee>();
            }
    
            public virtual void AddProduct(Product product)
            {
                product.StoresStockedIn.Add(this);
                Products.Add(product);
            }
    
            public virtual void AddEmployee(Employee employee)
            {
                employee.Store = this;
                Staff.Add(employee);
            }
    
            public override int GetHashCode()
            {
                return Name.GetHashCode();
            }
    
            public override bool Equals(object obj)
            {
                Store obj_Store;
                obj_Store = obj as Store;
                if (obj_Store == null)
                {
                    return false;
                }
                if (obj_Store.Name != this.Name)
                {
                    return false;
                }
                return true;
            }
    
    
    
    
        }
    }
    

    Product Mapping And Class

        namespace compoundIDtest.Domain.Mappings
        {
            public class ProductMap : ClassMap<Product>
            {
                public ProductMap()
                {
                    Id(x => x.Id).Column("Product_id");
                    Map(x => x.Name);
                    Map(x => x.Price);
                    HasManyToMany(x => x.StoresStockedIn)
                      .Cascade.All()
                      .Inverse()
                      .Table("StoreProduct");
                }
            }
        }
    
    
    namespace compoundIDtest.Domain.Entities
    {
        public class Product
        {
            public virtual int Id { get; private set; }
            public virtual string Name { get; set; }
            public virtual double Price { get; set; }
            public virtual IList<Store> StoresStockedIn { get; set; }
            public virtual IList<StoreProduct> StoreProducts { get; set; }
            public Product()
            {
                StoresStockedIn = new List<Store>();
                StoreProducts = new List<StoreProduct>();
            }
    
    
                public override int GetHashCode()
                {
                    return Name.GetHashCode();
                }
    
                public override bool Equals(object obj)
                {
                    Product obj_Product;
                    obj_Product = obj as Product;
                    if (obj_Product == null)
                    {
                        return false;
                    }
                    if (obj_Product.Name != this.Name)
                    {
                        return false;
                    }
                    return true;
                }
    
    
            }
        }
    

    And StoreProduct

    namespace compoundIDtest.Domain.Mappings
    {
        public class Order_DetailMap : ClassMap<StoreProduct>
        {
            public Order_DetailMap()
            {
                Table("StoreProduct");
                LazyLoad();
                CompositeId().KeyReference(x => x.Store, "Store_id").KeyReference(x => x.Product, "Product_id");
                References(x => x.Store, "Store_id").Not.Update().Not.Insert().Cascade.All();
                References(x => x.Product, "Product_id").Not.Update().Not.Insert().Cascade.All();
                Map(x => x.ExtraBit);
            }
        }
    
    }
    
    namespace compoundIDtest.Domain.Entities
    {
        public class StoreProduct
        {
            public StoreProduct(){}
    
            public virtual Store Store { get; set; }
            public virtual Product Product { get; set; }
            public virtual String ExtraBit { get; set; }
    
            public override int GetHashCode()
            {
    
                if (this.ExtraBit != null)
                {
                    return Store.GetHashCode() + Product.GetHashCode() + ExtraBit.GetHashCode();
                }
    
                return Store.GetHashCode() + Product.GetHashCode();
    
            }
    
            public override bool Equals(object obj)
            {
                StoreProduct obj_StoreProduct;
                obj_StoreProduct = obj as StoreProduct;
                if (obj_StoreProduct == null)
                {
                    return false;
                }
                if (obj_StoreProduct.Product != this.Product && obj_StoreProduct.Store != this.Store && obj_StoreProduct.ExtraBit != this.ExtraBit)
                {
                    return false;
                }
                return true;
            }
    
        }
    }
    

    And here is code for an app to test the above:

    using System;
    using System.IO;
    using compoundIDtest.Domain.Entities;
    using FluentNHibernate.Cfg;
    using FluentNHibernate.Cfg.Db;
    using NHibernate;
    using NHibernate.Cfg;
    using NHibernate.Tool.hbm2ddl;
    using FluentNHibernate.Conventions;
    
    
    namespace compoundIDtest
    {
        class Program
        {
            private const string DbFile = "firstProgram.db";
    
            static void Main()
            {
                // create our NHibernate session factory
                var sessionFactory = CreateSessionFactory();
    
                using (var session = sessionFactory.OpenSession())
                {
                    // populate the database
                    using (var transaction = session.BeginTransaction())
                    {
                        // create a couple of Stores each with some Products and Employees
                        var barginBasin = new Store { Name = "Bargin Basin" };
                        var superMart = new Store { Name = "SuperMart" };
                        var CornerShop = new Store { Name = "Corner Shop" };
    
    
                        var potatoes = new Product { Name = "Potatoes", Price = 3.60 };
                        var fish = new Product { Name = "Fish", Price = 4.49 };
                        var milk = new Product { Name = "Milk", Price = 0.79 };
                        var bread = new Product { Name = "Bread", Price = 1.29 };
                        var cheese = new Product { Name = "Cheese", Price = 2.10 };
                        var waffles = new Product { Name = "Waffles", Price = 2.41 };
                        var poison = new Product { Name = "Poison", Price = 1.50 };
    
    
                        var daisy = new Employee { FirstName = "Daisy", LastName = "Harrison" };
                        var jack = new Employee { FirstName = "Jack", LastName = "Torrance" };
                        var sue = new Employee { FirstName = "Sue", LastName = "Walkters" };
                        var bill = new Employee { FirstName = "Bill", LastName = "Taft" };
                        var joan = new Employee { FirstName = "Joan", LastName = "Pope" };
    
                        var storeproduct = new StoreProduct { Store = CornerShop, Product = poison, ExtraBit = "Extra Bit"}; 
    
                        //session.SaveOrUpdate(CornerShop);
                        //session.SaveOrUpdate(poison);
    
                        session.Save(storeproduct);
    
    
                        // add products to the stores, there's some crossover in the products in each
                        // store, because the store-product relationship is many-to-many
                        AddProductsToStore(barginBasin, potatoes, fish, milk, bread, cheese);
                        AddProductsToStore(superMart, bread, cheese, waffles);
    
                        // add employees to the stores, this relationship is a one-to-many, so one
                        // employee can only work at one store at a time
                        AddEmployeesToStore(barginBasin, daisy, jack, sue);
                        AddEmployeesToStore(superMart, bill, joan);
    
                        // save both stores, this saves everything else via cascading
                        session.SaveOrUpdate(barginBasin);
                        session.SaveOrUpdate(superMart);
                        //session.SaveOrUpdate(CornerShop);
                        //session.SaveOrUpdate(poison);
                        //session.SaveOrUpdate(storeproduct);
    
                        transaction.Commit();
    
                    }
                }
    
                using (var session = sessionFactory.OpenSession())
                {
                    // retreive all stores and display them
                    using (var transaction = session.BeginTransaction())
                    {
                        var products = session.CreateCriteria(typeof(Product))
                            .List<Product>();
    
                        foreach (var product in products)
                        {
                            product.Price = 100;
                            session.SaveOrUpdate(product);
    
                        }
    
    
    
                        var storeproducts = session.CreateCriteria(typeof(StoreProduct)).List<StoreProduct>();
    
    
                        foreach (StoreProduct storeproduct in storeproducts)
                        {
    
                            if (storeproduct.Store.Name == "SuperMart")
                            {
                                storeproduct.ExtraBit = "Thank you, come again";
                            }
    
                            session.SaveOrUpdate(storeproduct);
    
                        }
    
                        transaction.Commit();
    
                    }
                }
    
    
    
                Console.ReadKey();
            }
    
            private static ISessionFactory CreateSessionFactory()
            {
                return Fluently.Configure()
                    .Database(SQLiteConfiguration.Standard
                        .UsingFile(DbFile))
                    .Mappings(m =>
                        m.FluentMappings.AddFromAssemblyOf<Program>())
                    .ExposeConfiguration(BuildSchema)
                    .BuildSessionFactory();
            }
    
            private static void BuildSchema(Configuration config)
            {
                // delete the existing db on each run
                if (File.Exists(DbFile))
                    File.Delete(DbFile);
    
                // this NHibernate tool takes a configuration (with mapping info in)
                // and exports a database schema from it
                new SchemaExport(config)
                    .Create(false, true);
            }
    
            private static void WriteStorePretty(Store store)
            {
                Console.WriteLine(store.Name);
                Console.WriteLine(" Products:");
    
                foreach (var product in store.Products)
                {
                    Console.WriteLine(" " + product.Name);
                }
    
                Console.WriteLine(" Staff:");
    
                foreach (var employee in store.Staff)
                {
                    Console.WriteLine(" " + employee.FirstName + " " + employee.LastName);
                }
    
                Console.WriteLine();
            }
    
            public static void AddProductsToStore(Store store, params Product[] products)
            {
                foreach (var product in products)
                {
                    store.AddProduct(product);
                }
            }
    
            public static void AddEmployeesToStore(Store store, params Employee[] employees)
            {
                foreach (var employee in employees)
                {
                    store.AddEmployee(employee);
                }
            }
        }
    }
    

    解决方案

    I had a mapping pretty much identical to this and the way I ended up mapping it was like this:

    public class Order_DetailMap : ClassMap<StoreProduct>
    {
        public Order_DetailMap()
        {
            Table("StoreProduct");
            CompositeId()
                .KeyReference(x => x.Store, "Store_id")
                .KeyReference(x => x.Product, "Product_id");
    
            Map(x => x.ExtraBit);
        }
    }
    

    Inside of my Store and Product classes I have add and remove methods that make the creation of this middle class almost invisible. Example below:

    public class Store
    {
        public IList<StoreProduct> StoreProducts { get; set; }
    
        //Other properties and Constructors     
    
        public virtual void AddProduct(Product productToAdd, string extraBit)
        {
            StoreProduct newStoreProduct = new StoreProduct(this, productToAdd, extraBit);
            storeProducts.Add(newStoreProduct);
        }
    }
    

    In addition to the above I had HasMany's to a StoreProduct collection in my Store and Product classes that are set to Cascade.AllDeleteOrphan()

    I was never able to be able to map the StoreProduct such that when it was saved by itself it would create a new Store and a new Product. I had to eventually map it like the above. So your Store or Product will need to exist before you actually create the relationship (StoreProduct) between them depending on which side you are creating your new StoreProduct from.

    Edit:

    You may also be able to map it like this to achieve what you are wanting:

    public class Order_DetailMap : ClassMap<StoreProduct>
    {
        public Order_DetailMap()
        {
            Table("StoreProduct");
            CompositeId()
                .KeyReference(x => x.Store, "Store_id")
                .KeyReference(x => x.Product, "Product_id");
    
            References(x => x.Store, "Store_id")
                .Not.Update()
                .Not.Insert()
                .Cascade.All();
    
            References(x => x.Product, "Product_id")
                .Not.Update()
                .Not.Insert()
                .Cascade.All();
    
            Map(x => x.ExtraBit);
        }
    }
    

    这篇关于流利Nhibernate:试图用复合键创建实体,也是两个引用的关键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆