(Fluent) NHibernate composite-id problem : MySQL complains that the parameter index is out of bounds
I'm using Fluent NHibernate to create an ASP.NET MVC project, with Submissions and Votes (Up/Down) by Users.
Of course, Users can vote submission Up or Down. To record this, I created a middle table, SubmissionVote, which contain the following fields:
submissionId (int)
userId (int)
score (enum: up/down)
Here are my mappings:
Submission
Id(x => x.Id);
...
References开发者_开发问答(x => x.User).Column("userID").Not.LazyLoad();
HasMany(x => x.Votes).Cascade.All().KeyColumn("submissionID").Table("SubmissionVote").Not.LazyLoad();
Table("Submission");
User
Id(x => x.Id);
...
HasMany(x => x.Submission).Inverse().KeyColumn("userID").Cascade.All();
HasMany(x => x.SubmissionVotes).KeyColumn("userID").Cascade.All().Table("SubmissionVote");
SubmissionVote
Map(x => x.Vote).Column("score");
CompositeId().KeyProperty(x => x.Submission.Id, "submissionID").KeyProperty(x => x.User.Id, "userID");
References(x => x.Submission).Column("submissionID");
References(x => x.User).Column("userID");
Since the middle table in my DB has a score field, I created the SubmissionVote class the represent it. The user and submission fields in that class are many-to-one relationships to their respective classes.
The problem is this: the SubmissionVote class need to have an ID property, otherwise NHibernate produces an error. That should not be the case, since the ID for a SubmissionVote is a composite-id, as represented in the mapping.
I can live with, but it causes another problem. When I try to save a submission with a few SubmissionVotes in it, using session.SaveOrUpdate(submission), I get this error a ArrayOutOfBounds exception thrown by MySQL, like in this question: How can I use a composite-id with a class as the id field in fluent nhibernate?.
Looking at the NHibernate logs, I can see the query that is sent to MySQL.
14:53:07.358 [9] DEBUG ... - Building an IDbCommand object for the SqlString: INSERT INTO `SubmissionVote` (score, submissionID, userID) VALUES (?, ?, ?)
14:53:07.361 [9] DEBUG ... - binding 'Up' to parameter: 0
14:53:07.367 [9] DEBUG NHibernate.Type.Int32Type - binding '183' to parameter: 1
14:53:07.367 [9] DEBUG NHibernate.Engine.IdentifierValue - unsaved-value: 0
14:53:07.367 [9] DEBUG NHibernate.Type.Int32Type - binding '2' to parameter: 2
14:53:07.367 [9] DEBUG NHibernate.Type.Int32Type - binding '0' to parameter: 3
Apparently, NHibernate tries to include a default "ID" value ('0') to the query (probably the ID property I added to the SubmissionVote).
Are the two problems related? How can I solve this problem?
Thank you very much!
Edit
Here is my (partial, but relevent) schema produced by NHibernate.
create table submission (
Id INTEGER NOT NULL AUTO_INCREMENT,
CreationDate DATETIME,
BeginDate DATETIME,
EndDate DATETIME,
Content VARCHAR(255),
userID INTEGER,
primary key (Id)
)
create table User (
Id INTEGER NOT NULL AUTO_INCREMENT,
UserName VARCHAR(255) unique,
Password VARCHAR(255),
Email VARCHAR(255),
primary key (Id)
)
create table `submissionVote` (
submissionID INTEGER not null,
userID INTEGER not null,
score VARCHAR(255),
primary key (submissionID, userID)
)
alter table `submissionVote`
add index (submissionID),
add constraint FKC2AE73C56C66D2D5
foreign key (submissionID)
references submission (Id)
alter table `submissionVote`
add index (userID),
add constraint FKC2AE73C5EC6C1277
foreign key (userID)
references User (Id)
alter table submission
add index (userID),
add constraint FKE6354599EC6C1277
foreign key (userID)
references User (Id)
I found the solution! Actually, I had to specify to NHibernate that the composite-id also happens to be my references.
The new mappings looks like this:
Map(x => x.Vote).Column("score");
CompositeId().KeyReference(x => x.Submission, "submissionID").KeyReference(x => x.User, "userID");
精彩评论