IndexOutOfRangeException 深入 NHibernate 的内部
我有以下映射:
public class SecurityMap : ClassMap<Security>
{
public SecurityMap()
{
Table("Security");
CompositeId().KeyProperty(k => k.Id, "SecurityId").KeyProperty(k => k.EndDate);
Map(x => x.LastUpdateUser);
References(x => x.Company).Columns("CompanyId", "EndDate");
References(x => x.PrimaryListing).Columns("PrimaryListingId", "EndDate");
}
}
public class ListingMap : ClassMap<Listing>
{
public ListingMap()
{
Table("Listing");
CompositeId().KeyProperty(k => k.Id, "ListingID").KeyProperty(k => k.EndDate);
References(x => x.Security).Columns("SecurityId","EndDate");
}
}
public class CompanyMap : ClassMap<Company>
{
public CompanyMap()
{
Table("Company");
CompositeId().KeyProperty(k => k.Id, "CompanyID").KeyProperty(k => k.EndDate);
HasMany(x => x.Securities).KeyColumns.Add("CompanyId", "EndDate");
}
}
当我尝试运行此测试时:
[Test]
public void can_update_a_security()
{
var repo = IoC.Resolve<ISecurityRepository>();
int someSecurity = 1;
using (var work = IoC.Resolve<IUnitOfWorkManager>().Current)
{
Security security = repo.Get(someSecurity);
security.ShouldNotBeNull();
security.LastUpdateUser = "Dirk Diggler" + DateTime.Now.Ticks;
repo.Save(security);
work.Commit();
}
}
我在 NHibernate 内部深处收到以下错误:
执行 System.IndexOutOfRangeException:索引 6 无效 计数 = 6 的 SqlParameterCollection。 在 System.Data.SqlClient.SqlParameterCollection.RangeCheck(Int32 指数) 在 System.Data.SqlClient.SqlParameterCollection.GetParameter(Int32 指数) 在 System.Data.Common.DbParameterCollection.System.Collections.IList.get_Item(Int32 指数) s:\NHibernate\NHibernate\src\NHibernate\Type\DateTimeType.cs(65,0): 在 NHibernate.Type.DateTimeType.Set(IDbCommand st,对象值,Int32 索引) s:\NHibernate\NHibernate\src\NHibernate\Type\NullableType.cs(180,0): 在 NHibernate.Type.NullableType.NullSafeSet(IDbCommand cmd,对象值,Int32 索引) s:\NHibernate\NHibernate\src\NHibernate\Type\NullableType.cs(139,0): 在 NHibernate.Type.NullableType.NullSafeSet(IDbCommand st,对象值,Int32 索引, ISessionImplementor 会话) s:\NHibernate\NHibernate\src\NHibernate\Type\ComponentType.cs(213,0): 在 NHibernate.Type.ComponentType.NullSafeSet(IDbCommand st,对象值,Int32 开始, ISessionImplementor 会话) s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2393,0): 在 NHibernate.Persister.Entity.AbstractEntityPersister.脱水(对象 id,对象[]字段,对象rowId, 布尔值[]包括属性,布尔值[][] includeColumns、Int32 表、 IDb命令语句, ISessionImplementor 会话,Int32 指数) s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2754,0): 在 NHibernate.Persister.Entity.AbstractEntityPersister.Update(对象 id、对象 [] 字段、对象 [] oldFields、对象 rowId、布尔值[] includeProperty、Int32 j、对象 旧版本、对象 obj、SqlCommandInfo sql、ISessionImplementor 会话) s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2666,0): 在 NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(对象 id、对象 [] 字段、对象 [] oldFields、对象 rowId、布尔值[] includeProperty、Int32 j、对象 旧版本、对象 obj、SqlCommandInfo sql、ISessionImplementor 会话) s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2940,0): 在 NHibernate.Persister.Entity.AbstractEntityPersister.Update(对象 id、Object[] 字段、Int32[] 脏字段,布尔值 有DirtyCollection,对象[] 旧字段,对象旧版本,对象 obj、对象 rowId、ISessionImplementor 会议) s:\NHibernate\NHibernate\src\NHibernate\Action\EntityUpdateAction.cs(78,0): 在 NHibernate.Action.EntityUpdateAction.Execute() s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(130,0): 在 NHibernate.Engine.ActionQueue.Execute(IExecutable 可执行) s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(113,0): 在 NHibernate.Engine.ActionQueue.ExecuteActions(IList 列表) s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(147,0): 在 NHibernate.Engine.ActionQueue.ExecuteActions() s:\NHibernate\NHibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs(241,0): 在 NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource 会议) s:\NHibernate\NHibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs(19,0): 在 NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent 事件) s:\NHibernate\NHibernate\src\NHibernate\Impl\SessionImpl.cs(1478,0): 在 NHibernate.Impl.SessionImpl.Flush() s:\NHibernate\NHibernate\src\NHibernate\Transaction\AdoTransaction.cs(187,0): 在 NHibernate.Transaction.AdoTransaction.Commit() 在 lambda_method(ExecutionScope, ITransaction)
现在有趣的是,如果我注释掉 SecurityMap 中对 Company 或 PrimaryListing 的引用,我不会收到错误。我评论哪一个似乎并不重要。仅当我同时拥有两者时才会发生该错误。
当更新实际完成时,NHProf 向我显示了此更新:
UPDATE Security
SET LastUpdateUser = '2010-02-19T08:09:24.00' /* @p0 */,
CompanyId = 54199 /* @p1 */,
EndDate = '9999-12-31T00:00:00.00' /* @p2 */
WHERE SecurityId = 1 /* @p3 */
AND EndDate = '9999-12-31T00:00:00.00' /* @p4 */
我不确定为什么它要更新 CompanyId 和 EndDate,但我怀疑它是相关的。
有人有想法吗?解决方法将不胜感激。
I have the following mappings:
public class SecurityMap : ClassMap<Security>
{
public SecurityMap()
{
Table("Security");
CompositeId().KeyProperty(k => k.Id, "SecurityId").KeyProperty(k => k.EndDate);
Map(x => x.LastUpdateUser);
References(x => x.Company).Columns("CompanyId", "EndDate");
References(x => x.PrimaryListing).Columns("PrimaryListingId", "EndDate");
}
}
public class ListingMap : ClassMap<Listing>
{
public ListingMap()
{
Table("Listing");
CompositeId().KeyProperty(k => k.Id, "ListingID").KeyProperty(k => k.EndDate);
References(x => x.Security).Columns("SecurityId","EndDate");
}
}
public class CompanyMap : ClassMap<Company>
{
public CompanyMap()
{
Table("Company");
CompositeId().KeyProperty(k => k.Id, "CompanyID").KeyProperty(k => k.EndDate);
HasMany(x => x.Securities).KeyColumns.Add("CompanyId", "EndDate");
}
}
When I attempt to run this test:
[Test]
public void can_update_a_security()
{
var repo = IoC.Resolve<ISecurityRepository>();
int someSecurity = 1;
using (var work = IoC.Resolve<IUnitOfWorkManager>().Current)
{
Security security = repo.Get(someSecurity);
security.ShouldNotBeNull();
security.LastUpdateUser = "Dirk Diggler" + DateTime.Now.Ticks;
repo.Save(security);
work.Commit();
}
}
I get the following error deep in the bowels of NHibernate:
Execute
System.IndexOutOfRangeException: Invalid index 6 for this
SqlParameterCollection with Count=6.
at System.Data.SqlClient.SqlParameterCollection.RangeCheck(Int32
index)
at System.Data.SqlClient.SqlParameterCollection.GetParameter(Int32
index)
at System.Data.Common.DbParameterCollection.System.Collections.IList.get_Item(Int32
index)
s:\NHibernate\NHibernate\src\NHibernate\Type\DateTimeType.cs(65,0):
at
NHibernate.Type.DateTimeType.Set(IDbCommand
st, Object value, Int32 index)
s:\NHibernate\NHibernate\src\NHibernate\Type\NullableType.cs(180,0):
at
NHibernate.Type.NullableType.NullSafeSet(IDbCommand
cmd, Object value, Int32 index)
s:\NHibernate\NHibernate\src\NHibernate\Type\NullableType.cs(139,0):
at
NHibernate.Type.NullableType.NullSafeSet(IDbCommand
st, Object value, Int32 index,
ISessionImplementor session)
s:\NHibernate\NHibernate\src\NHibernate\Type\ComponentType.cs(213,0):
at
NHibernate.Type.ComponentType.NullSafeSet(IDbCommand
st, Object value, Int32 begin,
ISessionImplementor session)
s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2393,0):
at
NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object
id, Object[] fields, Object rowId,
Boolean[] includeProperty, Boolean[][]
includeColumns, Int32 table,
IDbCommand statement,
ISessionImplementor session, Int32
index)
s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2754,0):
at
NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object
id, Object[] fields, Object[]
oldFields, Object rowId, Boolean[]
includeProperty, Int32 j, Object
oldVersion, Object obj, SqlCommandInfo
sql, ISessionImplementor session)
s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2666,0):
at
NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object
id, Object[] fields, Object[]
oldFields, Object rowId, Boolean[]
includeProperty, Int32 j, Object
oldVersion, Object obj, SqlCommandInfo
sql, ISessionImplementor session)
s:\NHibernate\NHibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs(2940,0):
at
NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object
id, Object[] fields, Int32[]
dirtyFields, Boolean
hasDirtyCollection, Object[]
oldFields, Object oldVersion, Object
obj, Object rowId, ISessionImplementor
session)
s:\NHibernate\NHibernate\src\NHibernate\Action\EntityUpdateAction.cs(78,0):
at
NHibernate.Action.EntityUpdateAction.Execute()
s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(130,0):
at
NHibernate.Engine.ActionQueue.Execute(IExecutable
executable)
s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(113,0):
at
NHibernate.Engine.ActionQueue.ExecuteActions(IList
list)
s:\NHibernate\NHibernate\src\NHibernate\Engine\ActionQueue.cs(147,0):
at
NHibernate.Engine.ActionQueue.ExecuteActions()
s:\NHibernate\NHibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs(241,0):
at
NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource
session)
s:\NHibernate\NHibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs(19,0):
at
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent
event)
s:\NHibernate\NHibernate\src\NHibernate\Impl\SessionImpl.cs(1478,0):
at NHibernate.Impl.SessionImpl.Flush()
s:\NHibernate\NHibernate\src\NHibernate\Transaction\AdoTransaction.cs(187,0):
at
NHibernate.Transaction.AdoTransaction.Commit()
at lambda_method(ExecutionScope , ITransaction )
Now the interesting thing is if I comment out the reference to Company or PrimaryListing in the SecurityMap, I don't get the error. It doesn't seem to matter which I comment out. The error only happens when I have both.
When the update actually goes through NHProf shows me this update:
UPDATE Security
SET LastUpdateUser = '2010-02-19T08:09:24.00' /* @p0 */,
CompanyId = 54199 /* @p1 */,
EndDate = '9999-12-31T00:00:00.00' /* @p2 */
WHERE SecurityId = 1 /* @p3 */
AND EndDate = '9999-12-31T00:00:00.00' /* @p4 */
I am not sure why it is updating CompanyId and EndDate, but I suspect it is related.
Any one have ideas? Work arounds would be greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,这是一个常见问题,您在映射定义中使用了两次
列“EndDate”
(对于 Company 和 PrimaryListing),这是不允许的。其中之一必须消失,或者有一个额外的 EndDate 列(每个关联一个)也检查这一点
nHibernate 2.0 - 映射复合 ID *和* 多对一关系导致“无效索引”错误
和
Yes its a common problem, you are using the
Column "EndDate"
twice in your mapping definition (for both Company and PrimaryListing) and that is not allowed. One of them has to go, or have an additional EndDate column (one for each association)check this too
nHibernate 2.0 - mapping a composite-id *and* many-to-one relationship causes "invalid index" error
and
http://devlicio.us/blogs/derik_whittaker/archive/2009/03/19/nhibernate-and-invalid-index-n-for-this-sqlparametercollection-with-count-n-error.aspx