0

バッチ挿入を実行しようとしていますが、うまくいきません。私はこれが機能していると思っていましたが、何かが壊れているようです。

編集- データベーススキーマは次のとおりです。

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
}

対応する流暢なマッピング:

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]");
    }
}

今私が言うとき:

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();

エラーがスローされます:

INSERT ステートメントが FOREIGN KEY 制約 "FK_ProductTopSellersCategory_Categories" と競合しました。データベース「xxx」、テーブル「dbo.Categories」、列「Id」で競合が発生しました。ステートメントは終了されました。

この例をできるだけ単純化しようとしました。助けていただければ幸いです。ありがとう

4

2 に答える 2

0

Category と ProductTopSellerCategory の間に 1 対多の関係があり、多側がマッピングされているだけです。通常、片側にマップされたコレクションで逆属性を使用しますが、それをマップしていないので、次のことをお勧めします。

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();
}

元のコードの問題は、NHibernate が新しい ProductTopSellerCategory を挿入してからカテゴリを更新しようとしていることです。逆属性が設定されていないため、これを行っています。セッションをフラッシュしてNHibernateに強制的に新しいカテゴリを挿入させると、問題が解決するはずです。

于 2013-07-20T13:30:36.077 に答える
0

私は解決策を見つけたと思います。ちょっとハックですが、エンティティとマッピングを変更する必要はありませんでした。この問題は、ID タイプの CategoryId がトップセラー エンティティの Category.Id と同じ参照を指していないために発生します。この問題を解決するには、トップセラーを挿入する直前に次を追加する必要があります。

topSeller.Id.CategoryId = topSeller.Category.Id;
于 2013-07-22T09:50:11.913 に答える