In a unidirectional many-to-many relationship between Registration
and Item
, where a Registration
has an ISet<Item> ItemsPurchased
and Item
has no reference back to registrations (it's not a useful way to explore the object graph), when I look at the SQL being generated, I see
INSERT INTO Registrations_Items (RegistrationId, ItemId) VALUES (@p0, @p1);@p0 = 1 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]
UPDATE Items SET Price = @p0, Name = @p1, [...], ListIndex = @p5, EventId = @p6 WHERE ItemId = @p7
The parameters passed to the update are correct, but nothing about the Item has changed, so the update is not needed.
Mapping is by automapping with this override in place for Registration
and no overrides for Item
. DB Schema looks completely correct. I removed all conventions and tested again and the behavior persisted, so it's not any of my mapping conventions that are doing this.
mapping.HasManyToMany(e => e.ItemsPurchased).AsSet().Cascade.All().Not.Inverse();
Why is NHibernate making this UPDATE
call and what can I do to stop it? It's not really hurting anything but it suggests that I did something wrong, so I'd like to figure out what.
Edit:
Per comment below, I created a unit test which creates an Event
(Item
must belong to an Event
), adds two Items
to it, evicts the first from session and flushes session, then Gets the first back by its ID.
I notice something odd in the SELECT items line below (2nd from bottom)
INSERT INTO Events (blah blah blah...)
select @@IDENTITY
INSERT INTO Items (Price, Name, StartDate, EndDate, ExternalID, ListIndex, EventId) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6);@p0 = 100.42 [Type: Decimal (0)], @p1 = 'Item 1' [Type: String (0)], @p2 = NULL [Type: DateTime (0)], @p3 = NULL [Type: DateTime (0)], @p4 = '123' [Type: String (0)], @p5 = 0 [Type: Int32 (0)], @p6 = 1 [Type: Int32 (0)]
select @@IDENTITY
SELECT blah blah blah FROM Events event0_ WHERE event0_.EventId=@p0;@p0 = 1 [Type: Int32 (0)]
SELECT itemsforsa0_.EventId as EventId1_, itemsforsa0_.ItemId as ItemId1_, itemsforsa0_.ListIndex as ListIndex1_, itemsforsa0_.ItemId as ItemId3_0_, itemsforsa0_.Price as Price3_0_, itemsforsa0_.Name as Name3_0_, itemsforsa0_.StartDate as StartDate3_0_, itemsforsa0_.EndDate as EndDate3_0_, itemsforsa0_.ExternalID as ExternalID3_0_, itemsforsa0_.ListIndex as ListIndex3_0_, itemsforsa0_.EventId as EventId3_0_ FROM Items itemsforsa0_ WHERE itemsforsa0_.EventId=@p0;@p0 = 1 [Type: Int32 (0)]
UPDATE Items SET Price = @p0, Name = @p1, StartDate = @p2, EndDate = @p3, ExternalID = @p4, ListIndex = @p5, EventId = @p6 WHERE ItemId = @p7;@p0 = 100.42000 [Type: Decimal (0)], @p1 = 'Item 1' [Type: String (0)], @p2 = NULL [Type: DateTime (0)], @p3 = NULL [Type: DateTime (0)], @p4 = '123' [Type: String (0)], @p5 = 0 [Type: Int32 (0)], @p6 = 1 [Type: Int32 (0)], @p7 = 1 [Type: Int32 (0)]
The table is created correctly:
create table Items (
ItemId INT IDENTITY NOT NULL,
Price NUMERIC(19,5) not null,
Name NVARCHAR(255) not null,
StartDate DATETIME null,
EndDate DATETIME null,
ExternalID NVARCHAR(255) not null,
ListIndex INT not null,
EventId INT not null,
primary key (ItemId)
)
The DateTimes are deliberately nullable because an item might not need to be date-specific (an example of something that is would be "early-bird registration").