Nhibernate 批插入-外键不工作
我正在尝试批量插入,但它不起作用。我原以为我能做到,但似乎有些东西坏了,如果有人能告诉我是什么,我将不胜感激 编辑-以下是数据库架构:Nhibernate 批插入-外键不工作,nhibernate,fluent-nhibernate,composite-key,Nhibernate,Fluent Nhibernate,Composite Key,我正在尝试批量插入,但它不起作用。我原以为我能做到,但似乎有些东西坏了,如果有人能告诉我是什么,我将不胜感激 编辑-以下是数据库架构: CREATE TABLE [dbo].[Categories]( [Id] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](100) NOT NULL, CONSTRAINT [PK_Categories] PRIMARY KEY CLUSTERED ([Id]) ) CREATE TAB
CREATE TABLE [dbo].[Categories](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
CONSTRAINT [PK_Categories] PRIMARY KEY CLUSTERED ([Id])
)
CREATE TABLE [dbo].[ProductTopSellersCategory](
[ProductId] [int] NOT NULL,
[CategoryId] [int] NOT NULL,
[Order] [int] NOT NULL,
CONSTRAINT [PK_ProductTopSellersCategory]
PRIMARY KEY CLUSTERED ([ProductId], [CategoryId])
)
ALTER TABLE [dbo].[ProductTopSellersCategory] ADD
CONSTRAINT [FK_ProductTopSellersCategory_Products]
FOREIGN KEY ([ProductId]) REFERENCES [dbo].[Products] ([Id]),
CONSTRAINT [FK_ProductTopSellersCategory_Categories]
FOREIGN KEY ([CategoryId]) REFERENCES [dbo].[Categories] ([Id])
我拥有以下实体:
public class Category {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
public class ProductTopSellerCategory {
public virtual ProductTopSellerCategoryIdentifier Id { get; set; }
private Product _product;
public virtual Product Product {
get { return _product; }
set { _product = value; Id.ProductId = _product.Id; }
}
private Category _category;
public virtual Category Category {
get { return _category; }
set { _category = value; Id.CategoryId = _category.Id; }
}
[Required]
public virtual int Order { get; set; }
public ProductTopSellerCategory() {
Id = new ProductTopSellerCategoryIdentifier();
}
}
[Serializable]
public class ProductTopSellerCategoryIdentifier {
public virtual int ProductId { get; set; }
public virtual int CategoryId { get; set; }
#region Composite Id Members
public override bool Equals(object obj) {
if (obj == null || !(obj is ProductTopSellerCategoryIdentifier))
return false;
var i = (ProductTopSellerCategoryIdentifier)obj;
return ProductId == i.ProductId && CategoryId == i.CategoryId;
}
public override int GetHashCode() {
return ToString().GetHashCode();
}
public override string ToString() {
return ProductId + "|" + CategoryId;
}
#endregion
}
使用相应的fluent映射:
public class CategoryMap : ClassMap<Category> {
public CategoryMap() {
Table("Categories");
Id(x => x.Id);
Map(x => x.Name);
}
}
public class ProductTopSellerCategoryMap : ClassMap<ProductTopSellerCategory> {
public ProductTopSellerCategoryMap() {
Table("ProductTopSellersCategory");
CompositeId(x => x.Id)
.KeyProperty(x => x.ProductId)
.KeyProperty(x => x.CategoryId);
References(x => x.Product).ReadOnly();
References(x => x.Category).ReadOnly();
Map(x => x.Order, "[Order]");
}
}
公共类类别映射:类映射{
公共类别映射(){
表(“类别”);
Id(x=>x.Id);
Map(x=>x.Name);
}
}
公共类ProductTopSellerCategoryMap:ClassMap{
公共产品TopSellerCategoryMap(){
表(“ProductTopSellersCategory”);
CompositeId(x=>x.Id)
.KeyProperty(x=>x.ProductId)
.KeyProperty(x=>x.CategoryId);
引用(x=>x.Product).ReadOnly();
引用(x=>x.Category).ReadOnly();
映射(x=>x.Order,“[Order]”;
}
}
现在当我说:
var category = new Category() { Name = "Test 1" };
var product = session.Get<Product>(1);
var topSeller = new ProductTopSellerCategory() { Product = product, Category = category };
session.SaveOrUpdate(category);
session.SaveOrUpdate(topSeller);
session.Transaction.Commit();
var category=new category(){Name=“Test 1”};
var product=session.Get(1);
var topSeller=new ProductTopSellerCategory(){Product=Product,Category=Category};
会话.保存或更新(类别);
会议。保存或更新(topSeller);
Commit();
它抛出错误:
INSERT语句与外键约束冲突
“FK_ProductTopSellersCategories_Categories”。冲突发生在
数据库“xxx”,表“dbo.Categories”,列“Id”。该声明已经发布
已经终止
我试图尽可能地简化这个例子。我非常感谢你的帮助。谢谢您在Category和ProductTopSellerCategory之间建立了一对多关系,只映射了多个侧面。通常情况下,您会在一侧映射的集合上使用反转属性,但您没有映射该属性,因此我建议:
using (var txn = session.BeginTransaction())
{
var category = new Category() { Name = "Test 1" };
session.Save(category);
session.Flush();
var product = session.Get<Product>(1);
var productTopSellerCategory = new ProductTopSellerCategory() { Product = product, Category = category };
session.Save(productTopSellerCategory);
txn.Commit();
}
使用(var txn=session.BeginTransaction())
{
var category=new category(){Name=“Test 1”};
会话.保存(类别);
session.Flush();
var product=session.Get(1);
var productTopSellerCategory=new productTopSellerCategory(){Product=Product,Category=Category};
session.Save(productTopSellerCategory);
提交();
}
原始代码的问题是NHibernate试图插入新的ProductTopSellerCategory,然后更新该类别。这样做是因为未设置反向属性。通过刷新会话强制NHibernate插入新类别应该可以解决问题。我想我已经找到了解决方案。这有点像黑客,但这意味着我不必更改我的实体和映射。出现此问题的原因是标识类型中的CategoryId与top sellers实体中的Category.Id指向的引用不同。要解决此问题,我需要在插入畅销书之前添加以下内容:
topSeller.Id.CategoryId = topSeller.Category.Id;
外键是从哪里来的?你是手工制作的还是Nhibernate制作的?如果是您自己创建的,请发布密钥的DDL。我已使用数据库架构更新了我的问题。谢谢,我尝试在插入类别后刷新,但遇到了相同的问题。我刚刚注意到ProductTopSellerCategory.category和.Product上的只读设置。ReadOnly将不允许设置该值,当您删除它时,原始代码可能会正常工作。如果这还不能解决问题,请分析您的应用程序,以便您能够准确地看到发生了什么。谢谢,我将在周一尝试,因为我在那之前都很忙。仅供参考,我使用的结构来自NHibernate博客。如果取消只读,则会出现错误:“Count=3的此SqlParameterCollection的索引3无效。”。我还尝试过向类别中添加一组Topseller(具有多个映射和一个反向),但我遇到了相同的问题。查看SQL,当它尝试插入畅销书时,它的类别id为0。如果您需要更多信息再次提供帮助,请告诉我。谢谢