19

私のシステムには、ShoppingCartとShoppingCartItemの2つのエンティティがあります。かなり一般的なユースケース。ただし、ShoppingCartを保存すると、どのアイテムもDBに保存されません。

オブジェクト内に、新しいShoppingCartオブジェクトを作成します。

ShoppingCart cart = CreateOrGetCart();

次に、データベースから取得した既存の製品を最初に追加します。

cart.AddItem(product);

これは、アイテムをIListに追加するための単純なラッパーです。

    public virtual void AddItem(Product product)
    {
        Items.Add(new ShoppingCartItem { Quantity = 1, Product = product });
    }

次に、リポジトリでSaveOrUpdateを呼び出します

Repository.SaveOrUpdate(cart);

これは次のようになります:

   public T SaveOrUpdate(T entity)
    {
        Session.SaveOrUpdate(entity);
        return entity;
    }

マッピングにFluentNHibernateを使用しています。

    public ShoppingCartItemMap()
    {
        WithTable("ShoppingCartItems");

        Id(x => x.ID, "ShoppingCartItemId");
        Map(x => x.Quantity);

        References(x => x.Cart, "ShoppingCartId").Cascade.SaveUpdate();
        References(x => x.Product, "ProductId");
    }


    public ShoppingCartMap()
    {
        WithTable("ShoppingCarts");

        Id(x => x.ID, "ShoppingCartId");
        Map(x => x.Created);
        Map(x => x.Username);

        HasMany<ShoppingCartItem>(x => x.Items)
            .IsInverse().Cascade.SaveUpdate()
            .WithKeyColumn("ShoppingCartId")
            .AsBag();
    }

データベーススキーマ(SQL Server 2005)もかなり一般的です。

CREATE TABLE [dbo].[ShoppingCarts]
(
[ShoppingCartID] [int] NOT NULL IDENTITY(1, 1),
[Username] [nvarchar] (50) NOT NULL,
[Created] [datetime] NOT NULL
)
GO
ALTER TABLE [dbo].[ShoppingCarts] ADD CONSTRAINT [PK_ShoppingCarts] PRIMARY KEY CLUSTERED ([ShoppingCartID])
GO



CREATE TABLE [dbo].[ShoppingCartItems]
(
[ShoppingCartItemId] [int] NOT NULL IDENTITY(1, 1),
[ShoppingCartId] [int] NOT NULL,
[ProductId] [int] NOT NULL,
[Quantity] [int] NOT NULL
)
GO
ALTER TABLE [dbo].[ShoppingCartItems] ADD CONSTRAINT [PK_ShoppingCartItems] PRIMARY KEY CLUSTERED ([ShoppingCartItemId])
GO
ALTER TABLE [dbo].[ShoppingCartItems] ADD CONSTRAINT [FK_ShoppingCartItems_Products] FOREIGN KEY ([ProductId]) REFERENCES [dbo].[Products] ([ProductId])
GO
ALTER TABLE [dbo].[ShoppingCartItems] ADD CONSTRAINT [FK_ShoppingCartItems_ShoppingCarts] FOREIGN KEY ([ShoppingCartId]) REFERENCES [dbo].[ShoppingCarts] ([ShoppingCartID])
GO

ShoppingCartをSaveOrUpdateすると、ShoppingCartItemsも保存されないのはなぜですか?

助けてください。

ありがとう

ベン

更新:トランザクションでラップすると、さらに情報が得られます:

列'ShoppingCartId'、テーブル'WroxPizza.dbo.ShoppingCartItems'に値NULLを挿入できません。列はnullを許可しません。INSERTは失敗します。ステートメントは終了されました。

これは新しいカートだからです。

4

8 に答える 8

3

私は流暢なnhibernateでこの正確な問題を抱えていました。1 対多の関係のマッピングに小さなバグがあり、関係が自動的に保存またはカスケードされないようです。 Fluent NHibernate グループへの投稿については、こちらを参照してください

どうやら、この問題に取り組んでいる人がいるようです。

これがあなたのコードの問題であるとは断言できませんが、私が抱えていた問題と非常によく似ています。それがいくつか役立つことを願っています!

于 2009-03-05T22:42:17.180 に答える
2

なぜ.Cascade.SaveUpdate()ラインに入れたのか

References(x => x.Cart, "ShoppingCartId").Cascade.SaveUpdate()

?

おそらく、関係の両端からカスケード保存/更新があるように見えるNHibernate(またはFluent NHibernate)を混乱させますか?

HasMany をカスケードするように構成するだけで、目的を達成するのに十分なはずです。

于 2009-02-13T12:58:33.013 に答える
1

Session.SaveOrUpdateをトランザクションでラップするか、直後に強制的にフラッシュしてみてください。

于 2009-02-08T01:56:59.573 に答える
0

カートアイテムが最初に保存され、次にカートが保存される可能性はありますか?したがって、子アイテムには使用する親IDがありませんか?

IDを取得するためだけに、作成時にカートをDBに明示的に保存してから、アイテムを追加して保存する必要がある場合があります。

于 2009-02-08T12:37:35.380 に答える
0

お気づきのとおり、(データベーススキーマで)フィールドをIdentityで定義したため、これらのフィールドはマップファイルで設定する必要があります。次のような例:

Id(x => x.ID, "ShoppingCartItemId").GeneratedBy.Identity();

Identityによって生成されるようにマッピングのIdentityフィールドを設定しなかったために発生するエラー。したがって、Save()を実行しようとすると、Identity列が生成されません(データベースでnull以外に設定されます)。その後、エラーが発生します。

于 2010-12-27T07:42:02.063 に答える
0

よくわかりませんが、NHibernateがオブジェクトの保存を子オブジェクトにカスケードするとは思いません。SaveOrUpdateを呼び出すコードは表示されませんが、その時点でShoppingCartItemsをループして、それぞれを個別に保存すると、それらも永続化されます。

于 2009-02-08T02:00:23.733 に答える
-1

NHibernateについては何も知りません(私が使用するOPFは私のためにこれを行います)が、集約ルート(ShoppingCart)を保存するときに、そのコードもその複合所有インスタンスをセッションにコミットする必要があるのではないでしょうか?

于 2009-02-08T12:32:22.927 に答える