【问题标题】:Mapping by code in NHibernate does not delete child elements in many to one mappingNHibernate中的代码映射不会删除多对一映射中的子元素
【发布时间】:2019-07-19 14:25:25
【问题描述】:

我有以下两个 C# 类:

public class Pet
{
    public virtual string Id { get; set; }

    public virtual string Name { get; set; }
}

public class PetOwner
{
    public virtual string Id { get; set; }
    public virtual Pet Pet { get; set; }
}

我正在通过代码映射它们。

在我的 PetOwner 类中,我有以下 Pet 的 ManyToOne 映射:

    ManyToOne<Pet>("Pet", map =>
         {
             map.Lazy(LazyRelation.Proxy);
             map.Column("Pet_Id");
             map.Cascade(Cascade.Persist | Cascade.DeleteOrphans); 
             map.Insert(true);
             map.Update(true);
         });

现在当我按如下方式在我的 PetOwner 类上调用 delete 时,它​​可以工作并且 Pet 也被删除:

var owner = session.QueryOver<PetOwner>().Take(1).List().FirstOrDefault();
session.Delete(owner);

但是下面的代码根本没有删除宠物(也没有报错)。

session.Query<PetOwner>().Delete();

现在这只是在我的单元测试中,在现实生活中会有一个 where 子句,我可能不会删除所有项目,但为什么这个删除与使用实际数据库实体的显式删除不同?

有没有办法让它按我的预期工作?

【问题讨论】:

    标签: c# nhibernate nhibernate-mapping cascading-deletes


    【解决方案1】:

    QueryOverQuery 版本之间存在差异。

    QueryOver 只删除一个实例。为此,它首先将实体加载到内存中 - 尊重一级缓存。这就是为什么您的Cascade 工作正常。

    Query 版本正在删除所有记录,是批量删除操作。它不会在内存中加载实例 - 不支持一级缓存。
    您问题中的Query 接口示例实际上是作为DML 工作的。在对实体进行操作(更新/删除)之前,它不会将实体加载到内存中。

    /// Delete all entities selected by the specified query. The delete operation is performed in the database without reading the entities out of it.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam>
    /// <param name="source">The query matching the entities to delete.</param>
    /// <returns>The number of deleted entities.</returns>
    public static int Delete<TSource>(this IQueryable<TSource> source)
    

    回复您的 cmets:

    我明白这一点,但它不认为它也应该去删除那些拥有的项目吗?

    由于没有使用一级缓存,因此实​​际上没有任何“拥有”。

    所以 NHibernate 不会自动运行类似“从 Id 所在的宠物中删除(从 PetOwners 中选择 Pet_Id)”之类的东西。

    使用Query API,您实际上是在进行批量删除——它适用于 DML 查询。所以; no NHibernate 不会生成您要求的 SQL。

    或者是来自一级缓存的信息类型?

    不是一级缓存;但是您选择的 API。这种类型的信息在映射中定义。但是,如何生成查询还取决于您使用的 API。你在这里使用Query API。

    所以出于好奇,即使我使用 hbm 映射文件,我最终也会遇到相同的情况?

    HBM 或代码映射无关紧要。两者都是一样的。

    如果用户不手动删除宠物,是否有一种方法至少可以让删除失败?就是通过代码使用映射。

    嗯...使用QueryOver;但它不支持批量操作。任何支持批量操作的 API 都不会生成您期望的查询。在数据库级别添加必要的约束;这样,你就会抛出异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      相关资源
      最近更新 更多