我有一个包含大量产品数据的正在运行的数据库,我试图为下面的结构获得(流畅的)NHibernate映射。
但是运行代码会导致错误: 外键(FK1F94D86A1A0EC427:Product [ProductDet1_id]))必须与引用的主键具有相同的列数(ProductDet1 [ProductNumber,ProductionLine])
因此在映射过程中出现了问题,但无法弄清楚它是什么。有人可以让我摆脱这个问题吗? : - )
(Ofcource我公布了表格中的所有具体细节,只是为了让它可读)
我们有一个产品表,其中产品数量与生产线的组合是唯一的。每个产品只能有一个ProductDet1,ProductDet2 ......等等。
MSSQL产品表:
CREATE TABLE [dbo].[Product] (
[Id] INT NOT NULL IDENTITY,
[ProductNumber] INT NOT NULL,
[ProductionLine] INT NOT NULL,
CONSTRAINT [AK_Product_ProductNumber] UNIQUE ([ProductNumber], [ProductionLine]),
CONSTRAINT [PK_Product] PRIMARY KEY ([Id])
);
MSSQL ProductDet1和ProductDet2表:
CREATE TABLE [dbo].[ProductDet1] (
[ProductNumber] INT NOT NULL,
[ProductionLine] INT NOT NULL,
[TheValue] VARCHAR (15) NULL,
CONSTRAINT [FK_ProductDet1_Product] FOREIGN KEY ([ProductNumber], [ProductionLine]) REFERENCES [Product]([ProductNumber],[ProductionLine]),
CONSTRAINT [AK_ProductDet1_ProductNumber] UNIQUE ([ProductNumber], [ProductionLine])
);
GO
CREATE INDEX [IX_ProductDet1_ProductNumber] ON [dbo].[ProductDet1] ([ProductNumber])
GO
CREATE INDEX [IX_ProductDet1_ProductionLine] ON [dbo].[ProductDet1] ([ProductionLine])
C#产品类:
public class Product
{
public Product ()
{
ProductDet1 = new ProductDet1();
ProductDet2 = new ProductDet2();
}
public virtual int Id { get; set; }
public virtual int ProductionLine { get; set; }
public virtual int ProductNumber { get; set; }
public virtual string ProductName { get; set; }
public virtual ProductDet1 ProductDet1 { get; set; }
public virtual ProductDet2 ProductDet2 { get; set; }
public override bool Equals(object obj)
{
// If parameter is null return false.
if (obj == null)
{
return false;
}
// If parameter cannot be cast to Reference return false.
var product = obj as Product;
if (product == null)
{
return false;
}
// Return true if the fields match:
return this.ProductionLine == product.ProductionLine && this.ProductNumber == product.ProductNumber;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
C#产品Det1和产品Det2类:
public class ProductDet1
{
public virtual int Id { get; set; }
public virtual int ProductionLine { get; set; }
public virtual int ProductNumber { get; set; }
public virtual string TheValue { get; set; }
public virtual Product Product { get; set; }
public override bool Equals(object obj)
{
// If parameter is null return false.
if (obj == null)
{
return false;
}
// If parameter cannot be cast to Reference return false.
var product = obj as ProductCRT;
if (product == null)
{
return false;
}
// Return true if the fields match:
return this.ProductionLine == product.ProductionLine && this.ProductNumber == product.ProductNumber;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
产品图:
public class ProductEntityMap : ClassMap<Product>
{
public ProductEntityMap()
{
Id(x => x.Id);
Map(x => x.ProductNumber);
Map(x => x.ProductionLine);
Map(x => x.ProductName);
References(x => x.ProductDet1).Cascade.All().Not.LazyLoad();
References(x => x.ProductDet2).Cascade.All().Not.LazyLoad();
}
}
产品Det 1和Det 2地图:
public class ProductDet1EntityMap : ClassMap<ProductDet1>
{
public ProductDet1EntityMap()
{
CompositeId().KeyProperty(x => x.ProductNumber).KeyProperty(x => x.ProductionLine);
Map(x => x.TheValue);
}
}
答案 0 :(得分:1)
略有不同的类结构和映射,它隐藏了det类的复杂性。它实际上设置了References()
上使用的列public class Product
{
private ProductDet ProductDet1 { get; set; }
private ProductDet ProductDet2 { get; set; }
protected Product() { } // make NHibernate happy
public Product(int productionLine, int productNumber) : this(new ProductKey(productionLine, productNumber)) { }
public Product(ProductKey key)
{
Key = key;
ProductDet1 = new ProductDet { ProductKey = Key };
ProductDet2 = new ProductDet { ProductKey = Key };
}
public virtual int ID { get; protected set; }
public virtual ProductKey Key { get; protected set; }
public virtual string Det1
{
get { return ProductDet1.Value; }
set { ProductDet1.Value = value; }
}
public virtual string Det2
{
get { return ProductDet2.Value; }
set { ProductDet2.Value = value; }
}
}
public class ProductKey
{
protected ProductKey() { } // make NHibernate happy
public ProductKey(int productionLine, int productNumber)
{
ProductionLine = productionLine;
ProductNumber = productNumber;
}
public virtual int ProductionLine { get; private set; }
public virtual int ProductNumber { get; private set; }
public override bool Equals(object obj)
{
var other = obj as ProductKey;
return other != null && other.ProductionLine == this.ProductionLine && other.ProductNumber == this.ProductNumber;
}
public override int GetHashCode()
{
return (ProductionLine << 16) + ProductNumber;
}
}
public class ProductDet
{
public virtual ProductKey ProductKey { get; set; }
public virtual string Value { get; set; }
}
public class ProductMap : ClassMap<Product>
{
public ProductMap()
{
Id(x => x.ID);
Component(x => x.Key, c =>
{
c.Map(k => k.ProductionLine).UniqueKey("product_key");
c.Map(k => k.ProductNumber).UniqueKey("product_key");
});
MapProductDetReference("ProductDet1");
MapProductDetReference("ProductDet2");
}
private void MapProductDetReference(string entityName)
{
References(Reveal.Member<Product, ProductDet>(entityName))
.Columns("ProductionLine", "ProductNumber")
.ReadOnly()
.EntityName(entityName)
.Cascade.All()
.Fetch.Join()
.Not.LazyLoad();
}
}
public abstract class ProductDetMap : ClassMap<ProductDet>
{
public ProductDetMap()
{
CompositeId(x => x.ProductKey)
.KeyProperty(k => k.ProductionLine)
.KeyProperty(k => k.ProductNumber);
Map(x => x.Value, "TheValue");
}
}
public class ProductDet1Map : ProductDetMap
{
public ProductDet1Map()
{
EntityName("ProductDet1");
Table("ProductDet1");
}
}
public class ProductDet2Map : ProductDetMap
{
public ProductDet2Map()
{
EntityName("ProductDet2");
Table("ProductDet2");
}
}