使用Fluent NHibernate更新实体,删除多对多关系中的关联
我有两个这样的实体:使用Fluent NHibernate更新实体,删除多对多关系中的关联,nhibernate,fluent-nhibernate,mapping,many-to-many,Nhibernate,Fluent Nhibernate,Mapping,Many To Many,我有两个这样的实体: public class Service { public virtual int ServiceId { get; set; } public virtual char LayoutCode { get; set; } public virtual string ServiceNameEn { get; set; } public virtual string ServiceNameTh { get; set; } public v
public class Service
{
public virtual int ServiceId { get; set; }
public virtual char LayoutCode { get; set; }
public virtual string ServiceNameEn { get; set; }
public virtual string ServiceNameTh { get; set; }
public virtual string ServiceDescEn { get; set; }
public virtual string ServiceDescTh { get; set; }
public virtual string ServicePhone { get; set; }
public virtual byte[] ServiceImage { get; set; }
public virtual bool Permanent { get; set; }
public virtual bool Active { get; set; }
public virtual bool IsAutoAssign { get; set; }
public virtual DateTime CreatedDatetime { get; set; }
public virtual DateTime LastUpdatedDatetime { get; set; }
public virtual string RedirectUrl { get; set; }
public virtual IList<Reply> Replies { get; set; }
public virtual IList<Employee> Employees { get; set; }
public virtual IList<ServicesOfUser> ServicesOfUser { get; set; }
private IList<Category> _categories = new List<Category>();
public virtual IEnumerable<Category> Categories
{
get
{
return _categories;
}
}
public virtual void Add(Category category)
{
if (!_categories.Any(x => x.CategoryId == category.CategoryId))
{
_categories.Add(category);
}
}
public virtual void Clear()
{
_categories.Clear();
}
}
提交时,我收到以下错误消息:
not-null property references a null or transient value ilu.src.Entities.Category.CategoryDescEn
完整堆栈跟踪:
at NHibernate.Engine.Nullability.CheckNullability(Object[] values, IEntityPersister persister, Boolean isUpdate)
at NHibernate.Event.Default.DefaultDeleteEventListener.DeleteEntity(IEventSource session, Object entity, EntityEntry entityEntry, Boolean isCascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.FireDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.Delete(String entityName, Object child, Boolean isCascadeDeleteEnabled, ISet transientEntities)
at NHibernate.Engine.CascadingAction.DeleteCascadingAction.Cascade(IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeToOne(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, Object child, CollectionType collectionType, CascadeStyle style, IType elemType, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object child, CascadeStyle style, Object anything, CollectionType type)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
at NHibernate.Event.Default.DefaultDeleteEventListener.CascadeBeforeDelete(IEventSource session, IEntityPersister persister, Object entity, EntityEntry entityEntry, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.DeleteEntity(IEventSource session, Object entity, EntityEntry entityEntry, Boolean isCascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.FireDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.Delete(String entityName, Object child, Boolean isCascadeDeleteEnabled, ISet transientEntities)
at NHibernate.Engine.CascadingAction.DeleteCascadingAction.Cascade(IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeToOne(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, Object child, CollectionType collectionType, CascadeStyle style, IType elemType, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object child, CascadeStyle style, Object anything, CollectionType type)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
at NHibernate.Event.Default.DefaultDeleteEventListener.CascadeBeforeDelete(IEventSource session, IEntityPersister persister, Object entity, EntityEntry entityEntry, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.DeleteEntity(IEventSource session, Object entity, EntityEntry entityEntry, Boolean isCascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.FireDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.Delete(String entityName, Object child, Boolean isCascadeDeleteEnabled, ISet transientEntities)
at NHibernate.Engine.Cascade.DeleteOrphans(String entityName, IPersistentCollection pc)
at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, Object child, CollectionType collectionType, CascadeStyle style, IType elemType, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object child, CascadeStyle style, Object anything, CollectionType type)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
at NHibernate.Event.Default.AbstractFlushingEventListener.CascadeOnFlush(IEventSource session, IEntityPersister persister, Object key, Object anything)
at NHibernate.Event.Default.AbstractFlushingEventListener.PrepareEntityFlushes(IEventSource session)
at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at ilu.src.Common.UnitOfWork.Commit() in D:\Arunsawad\iLertU\ilu\ilu\src\Common\UnitOfWork.cs:line 41
at ilu.Controllers.AdminController.SaveService(Nullable`1 id, String name, String nameth, String desc, String descth, String phone, String catids, String url, Char layoutcode, Boolean permanent, Boolean active, Boolean autoassign) in D:\Arunsawad\iLertU\ilu\ilu\Controllers\AdminController.cs:line 107
这里有我遗漏的东西吗
谢谢大家! 将级联声明为
Cascade.AllDeleteOrphan()
。另外,尝试将.Inverse()
添加到多对多映射之一
更多信息:
来自NHibernate文档编辑: 根据您得到的错误判断,您只需要初始化类别的
CategoryDescEn
属性,然后再尝试保存它。您尝试保存时,似乎是null
:
not null属性引用一个null或瞬时值
ilu.src.Entities.Category.CategoryDesk
谢谢你的帮助。我将
.Cascade.None().Inverse()
添加到CategoryMap,将.Cascade.AllDeleteOrphan()
添加到ServiceMap,因为我只为服务更新类别,对吗?但当我更新服务时,我收到一条消息,notnull属性引用类别属性上的null或瞬态值,这是怎么回事?不确定。显然,其中一个外键对象为null。当您离开类别映射上的.Cascade.SaveUpdate()
时会发生什么?你能说出哪个属性抛出错误吗?另外,如果你能用一个完整的映射更新你的帖子可能会有帮助。我已经解决了我的问题,实际上不是你告诉我的方式,但是你的回答对我帮助很大!谢谢你!好天气;)
public class CategoryMap : ClassMap<Category>
{
public CategoryMap()
{
Table("[SERVICE_CATEGORIES]");
Id(x => x.CategoryId)
.GeneratedBy.Identity()
.Column("category_id")
.CustomType("int")
.Access.Property()
.CustomSqlType("int")
.Not.Nullable();
Map(x => x.CategoryNameEn)
.Column("category_name_en")
.CustomType("string")
.Access.Property()
.CustomSqlType("varchar")
.Length(128)
.Not.Nullable();
Map(x => x.CategoryNameTh)
.Column("category_name_th")
.CustomType("string")
.Access.Property()
.CustomSqlType("nvarchar")
.Length(128)
.Not.Nullable();
Map(x => x.CategoryDescEn)
.Column("category_desc_en")
.CustomType("string")
.Access.Property()
.CustomSqlType("varchar")
.Length(3423423)
.Not.Nullable();
Map(x => x.CategoryDescTh)
.Column("category_desc_th")
.CustomType("string")
.Access.Property()
.CustomSqlType("nvarchar")
.Length(3243234)
.Not.Nullable();
Map(x => x.CategoryImage)
.Column("category_image")
.CustomType("BinaryBlob")
.Access.Property()
.Generated.Never()
.CustomSqlType("image")
.Length(131231)
.Nullable();
Map(x => x.Active)
.Column("active")
.CustomType("bool")
.Access.Property()
.CustomSqlType("bit")
.Not.Nullable();
Map(x => x.CreatedDatetime)
.Column("created_datetime")
.Access.Property()
.CustomType("DateTime")
.CustomSqlType("datetime")
.Not.Nullable();
Map(x => x.LastUpdatedDatetime)
.Column("last_updated_datetime")
.Access.Property()
.CustomType("DateTime")
.CustomSqlType("datetime")
.Not.Nullable();
HasManyToMany<Service>(x => x.Services)
.AsBag()
.Cascade.AllDeleteOrphan()
.Inverse()
.LazyLoad()
.Table("SERVICES_IN_CATEGORIES")
.ChildKeyColumns.Add("service_id", mapping => mapping.Name("service_id")
.SqlType("int")
.Not.Nullable())
.ParentKeyColumns.Add("category_id", mapping => mapping.Name("category_id")
.SqlType("int")
.Not.Nullable());
}
}
using (unitOfWork = new UnitOfWork(SessionFactory))
{
serviceRepo = new ServiceRepo(unitOfWork.Session);
try
{
Service service = new Service();
if (id != null)
service = serviceRepo.GetById((int)id);
// set values for service here
IList<Category> categories = new List<Category>();
// add some categories to service
serviceRepo.Save(service);
unitOfWork.Commit();
return service;
}
catch (Exception ex)
{
unitOfWork.Rollback();
return null;
}
}
service.Clear();
not-null property references a null or transient value ilu.src.Entities.Category.CategoryDescEn
at NHibernate.Engine.Nullability.CheckNullability(Object[] values, IEntityPersister persister, Boolean isUpdate)
at NHibernate.Event.Default.DefaultDeleteEventListener.DeleteEntity(IEventSource session, Object entity, EntityEntry entityEntry, Boolean isCascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.FireDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.Delete(String entityName, Object child, Boolean isCascadeDeleteEnabled, ISet transientEntities)
at NHibernate.Engine.CascadingAction.DeleteCascadingAction.Cascade(IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeToOne(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, Object child, CollectionType collectionType, CascadeStyle style, IType elemType, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object child, CascadeStyle style, Object anything, CollectionType type)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
at NHibernate.Event.Default.DefaultDeleteEventListener.CascadeBeforeDelete(IEventSource session, IEntityPersister persister, Object entity, EntityEntry entityEntry, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.DeleteEntity(IEventSource session, Object entity, EntityEntry entityEntry, Boolean isCascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.FireDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.Delete(String entityName, Object child, Boolean isCascadeDeleteEnabled, ISet transientEntities)
at NHibernate.Engine.CascadingAction.DeleteCascadingAction.Cascade(IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeToOne(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, Object child, CollectionType collectionType, CascadeStyle style, IType elemType, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object child, CascadeStyle style, Object anything, CollectionType type)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
at NHibernate.Event.Default.DefaultDeleteEventListener.CascadeBeforeDelete(IEventSource session, IEntityPersister persister, Object entity, EntityEntry entityEntry, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.DeleteEntity(IEventSource session, Object entity, EntityEntry entityEntry, Boolean isCascadeDeleteEnabled, IEntityPersister persister, ISet transientEntities)
at NHibernate.Event.Default.DefaultDeleteEventListener.OnDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.FireDelete(DeleteEvent event, ISet transientEntities)
at NHibernate.Impl.SessionImpl.Delete(String entityName, Object child, Boolean isCascadeDeleteEnabled, ISet transientEntities)
at NHibernate.Engine.Cascade.DeleteOrphans(String entityName, IPersistentCollection pc)
at NHibernate.Engine.Cascade.CascadeCollectionElements(Object parent, Object child, CollectionType collectionType, CascadeStyle style, IType elemType, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeCollection(Object parent, Object child, CascadeStyle style, Object anything, CollectionType type)
at NHibernate.Engine.Cascade.CascadeAssociation(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeProperty(Object parent, Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled)
at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything)
at NHibernate.Event.Default.AbstractFlushingEventListener.CascadeOnFlush(IEventSource session, IEntityPersister persister, Object key, Object anything)
at NHibernate.Event.Default.AbstractFlushingEventListener.PrepareEntityFlushes(IEventSource session)
at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at ilu.src.Common.UnitOfWork.Commit() in D:\Arunsawad\iLertU\ilu\ilu\src\Common\UnitOfWork.cs:line 41
at ilu.Controllers.AdminController.SaveService(Nullable`1 id, String name, String nameth, String desc, String descth, String phone, String catids, String url, Char layoutcode, Boolean permanent, Boolean active, Boolean autoassign) in D:\Arunsawad\iLertU\ilu\ilu\Controllers\AdminController.cs:line 107