TransactionException:事务未连接或已断开连接] NHibernate.Transaction.AdoTransaction.CheckNotZombied()+108
NHibernate.Transaction.AdoTransaction.Rollback()+144
我在使用NHibernate以下列方式查询时遇到上述错误:
public IEnumerable<Service> GetAllServicesByOrgType(OrganisationType orgType)
{
return NHibernateSession
.CreateCriteria<ServiceOrganisationType>()
.Add(Restrictions.Eq("OrganisationType", orgType))
.List<ServiceOrganisationType>()
.Select(x=>x.Service);
}
下面是我的数据库结构和FluentNHibernate映射和模型:
数据库结构
Service:
- Id(PK)
- Name (nvarchar)
ServiceOrganisationType (composite PK on OrganisationTypeId and ServiceId):
- OrganisationTypeId (PK)
- ServiceId (PK)
- LastUpdated
- LastUpdatedById
OrganisationType:
- Id (PK)
- OrganisationType (nvarchar)
ServiceOrganisationTypeMap:
public class ServiceOrganisationTypeMap : ClassMap<ServiceOrganisationType>
{
public ServiceOrganisationTypeMap()
{
CompositeId()
.KeyReference(x => x.Service, "ServiceId")
.KeyProperty(x => x.OrganisationType, "OrganisationTypeId");
References(x => x.LastUpdatedBy);
Map(x => x.LastUpdated);
}
}
ServiceMap:
public class ServiceMap : ClassMap<Service>
{
/// <summary>
/// Initializes a new instance of the ServiceMap class.
/// </summary>
public ServiceMap()
{
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Name);
HasMany(x => x.ServiceOrganisationTypes)
.KeyColumn("ServiceId")
.Inverse()
.Cascade
.AllDeleteOrphan();
// Other mappings...
}
}
OrganisationType是一个枚举:
public enum OrganisationType : long
{
FirstOrgTypeExample = 1,
SecondOrgTypeExample = 10,
ThirdOrgTypeExample = 30
}
服务模型类:
[Serializable]
public class Service : DomainObject
{
// Other model properties...
public virtual IList<ServiceOrganisationType> ServiceOrganisationTypes { get; set; }
}
ServiceOrganisationType模型类:
[Serializable]
public class ServiceOrganisationType : AuditedObject
{
[NotNull]
public virtual OrganisationType OrganisationType { get; set; }
[NotNull]
public virtual Service Service { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
var t = obj as ServiceOrganisationType;
if (t == null)
return false;
if (OrganisationType == t.OrganisationType && Service == t.Service)
return true;
return false;
}
public override int GetHashCode()
{
return (OrganisationType + "|" + Service.Id).GetHashCode();
}
}
对于Enum,我也使用了本文回答中描述的EnumConvention类:Enum to integer mapping causing updates on every flush。所以我的Accept方法中包含以下内容:
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(
// ... Other arguments ||
// We want all instance of OrganisationType to map to long
x.Property.PropertyType == typeof(OrganisationType)
);
}
我猜测CheckNotZombied是其他东西的症状。当我检查NHProf它显示一个SQL错误 - “System.Data.SqlClient.SqlException:将数据类型nvarchar转换为bigint时出错” - 并且NHib在查询ServiceOrganisationType表时生成了以下sql:
SELECT this_.ServiceId as ServiceId63_0_,
this_.OrganisationTypeId as Organisa2_63_0_,
this_.LastUpdated as LastUpda3_63_0_,
this_.LastUpdatedById as LastUpda4_63_0_
FROM MyDb.dbo.[ServiceOrganisationType] this_
WHERE this_.OrganisationTypeId = 'FirstOrgTypeExample' /* @p0 */
在WHERE子句中,它使用枚举的字符串值('FirstOrgTypeExample')而不是 long 值。我在条件查询期间尝试将OrganisationType强制转换为long,但随后抛出了一个映射异常:
NHibernate.QueryException:类型不匹配 NHibernate.Criterion.SimpleExpression:OrganisationType期望类型 MyProduct.MyProject.Core.OrganisationType,实际类型System.Int64
任何人都可以帮我解决一下如何让NHibernate在生成的sql中使用枚举值吗?
由于
答案 0 :(得分:1)
问题出在我的EnumConvention上。它没有处理复合键。该帖子中提供了解决方案:How can I make composite key enums use int in fluent nhibernate with a convention?
答案 1 :(得分:0)
OrganisationTypeId可以为空吗?如果是这样,你需要使用Accept方法来允许这样做,否则它将保持为字符串值。以下内容应该有效。
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect((x => x.Property.PropertyType.IsEnum &&
x.Property.PropertyType == typeof(OrganisationType)) ||
(x.Property.PropertyType.IsGenericType &&
x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
);
}