首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Fluent NHibernate -级联所有删除Orphan不做任何删除

Fluent NHibernate -级联所有删除Orphan不做任何删除
EN

Stack Overflow用户
提问于 2012-11-26 21:33:56
回答 2查看 8.3K关注 0票数 4

我有两个简单的类,它们相互引用为一对多的关系,定义如下:

代码语言:javascript
复制
public class Project
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Document> Documents { get; set; }
}

public class Document
{
    public virtual int Id { get; set; }
    public string FileName { get; set; }
}

我的映射被定义为:

代码语言:javascript
复制
public class ProjectMapping : ClassMap<Project>
{
    public ProjectMapping()
    {
        Table("Projects");
        Id(x => x.Id).Column("Project_Id").GeneratedBy.TriggerIdentity();
        HasMany(x => x.Documents)
            .Table("Documents")
            .KeyColumn("Document_Project_Id")
            .Cascade.AllDeleteOrphan()
            .Not.KeyNullable();
        Map(x => x.Name).Column("Project_Name");
    }
}

public class DocumentMapping : ClassMap<Document>
{
    public DocumentMapping()
    {
        Table("Documents");
        Id(x => x.Id).Column("Document_Id").GeneratedBy.TriggerIdentity();
        Map(x => x.FileName).Column("Document_File_Name");
    }
}

一切似乎都正常,添加/更新文档和调用session.Save(项目)反映了数据库中的正确更改,但是,如果要从与项目关联的文档列表中删除文档并调用session.Save(项目),则删除的文档永远不会从数据库中删除。

除了删除之外,还有什么其他的东西都能工作吗?

编辑: MVC 4项目是用Fluent NHibernate设置的,如下所示:

代码语言:javascript
复制
public class SessionFactoryHelper
{
    public static ISessionFactory CreateSessionFactory()
    {
        var c = Fluently.Configure();
        try
        {
            //Replace connectionstring and default schema
            c.Database(OdbcConfiguration.MyDialect.
                ConnectionString(x =>
                x.FromConnectionStringWithKey("DBConnect"))
                .Driver<NHibernate.Driver.OdbcDriver>()
                .Dialect<NHibernate.Dialect.Oracle10gDialect>())
                .ExposeConfiguration(cfg => cfg.SetProperty("current_session_context_class", "web"));
            c.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Project>());
            c.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Document>());
        }
        catch (Exception ex)
        {
            Log.WriteLine(ex.ToString());
        }
        return c.BuildSessionFactory();
    }
}

public class MvcApplication : System.Web.HttpApplication
{
    public static ISessionFactory SessionFactory { get; private set; }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();

        SessionFactory = SessionFactoryHelper.CreateSessionFactory();
    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        var session = SessionFactory.OpenSession();
        CurrentSessionContext.Bind(session);
    }

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        var session = CurrentSessionContext.Unbind(SessionFactory);
        session.Dispose();
    }
}

我的存储库定义如下:

代码语言:javascript
复制
public class Repository<T> : IRepository<T>
{
    public virtual ISession Session
    {
        get { return MvcApplication.SessionFactory.GetCurrentSession(); }
    }

    public T FindById(int iId)
    {
        return Session.Get<T>(iId);
    }

    public void Save(T obj)
    {
        using (var transaction = Session.BeginTransaction())
        {
            try
            {
                Session.Save(obj);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();

                Log.WriteLine(ex.ToString());
            }
        }
    }

    public T SaveOrUpdate(T obj)
    {
        using (var transaction = Session.BeginTransaction())
        {
            try
            {
                Session.SaveOrUpdate(obj);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();

                Log.WriteLine(ex.ToString());
            }
        }

        return obj;
    }

    public T Update(T obj)
    {
        using (var transaction = Session.BeginTransaction())
        {
            try
            {
                Session.Update(obj);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();

                Log.WriteLine(ex.ToString());
            }
        }

        return obj;
    }
}

我的ProjectsController中定义了两个操作,如下所示:

代码语言:javascript
复制
private IRepository<Project> repository;

public ProjectsController()
{
    repository = new Repository<Project>();
}

public ActionResult Edit(int iId)
{
    Project project = repository.FindById(iId);

    if (project == null)
        return HttpNotFound();

    return View(project);
}

[HttpPost]
public ActionResult Edit(Project project)
{
    project = repository.Update(project);

    return View(project);
}

如果我要删除第一个操作中的文档(没有HttpPost):

代码语言:javascript
复制
project.Documents.RemoveAt(0);
repository.Update(project);

从数据库中删除正确的行。但是,如果我要在带有HttpPost属性的操作中执行相同的操作,则行将永远不会被移除。

另外,如果我在带有project.Documents属性的操作中向HttpPost添加了一个文档,那么repository.Update(project)成功地添加了带有正确外键引用的项目行。只有当我删除文档时,此操作才会失败。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-11-27 07:22:43

级联设置似乎是正确的。所提到的问题可能在其他地方:

但是,如果我要从与项目相关的文档列表中删除一个文档

我怀疑是会话刷新模式,或者缺少更新父实体Project的显式调用,这是以前分离的。保证:

首先,Flush()被调用。如果project实例仍然保持在会话中,则可以更改默认的刷新行为。(例如没有事务的session.FlushMode = FlushMode.Never;Commit .)

代码语言:javascript
复制
// 1) checking the explicit Flush()
project.Documents.Remove(doc);
Session.Flush(); // this will delete that orphan

第二个可以被逐出project实例,需要显式的更新调用。

代码语言:javascript
复制
// 2) updating evicted project instance
project.Documents.Remove(doc);
Session.Update(project);
//Session.Flush(); // Session session.FlushMode = FlushMode.Auto

在这种情况下,设置反向将有助于减少使用UPDATE语句访问数据库的次数,重置对doc.Project = null的引用,然后执行DELETE。

票数 2
EN

Stack Overflow用户

发布于 2012-11-26 22:32:02

您是否尝试过将.Inverse添加到HasMany映射中?

而且,我对Not.KeyNullable并不熟悉。我觉得这里没必要。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13573511

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档