Pregunta

Tengo las dos entidades siguientes, con sus asignaciones:

public class VideoCategory : BaseEntity<VideoCategory>
{
    private readonly Iesi.Collections.Generic.ISet<VideoFolder> folders = new HashedSet<VideoFolder>();

    public VideoCategory()
    {

    }

    public VideoCategory(string name)
    {
        Name = name;
    }

    public string Name { get; set; }


    public IEnumerable<VideoFolder> Folders { get { return folders; } }

    public void AddFolder(VideoFolder videoFolder)
    {
        Contract.Requires(videoFolder != null);

        if (folders.Contains(videoFolder))
            return;

        folders.Add(videoFolder);
        videoFolder.AddCategory(this);
    }

    public void RemoveFolder(VideoFolder videoFolder)
    {
        folders.Remove(videoFolder);
        videoFolder.RemoveCategory(this);
    }

    public void ClearFolders()
    {
        folders.ForEach(f => f.RemoveCategory(this));

        folders.Clear();
    }
}

public class VideoFolder : BaseEntity<VideoFolder>
{
    private readonly Iesi.Collections.Generic.ISet<VideoCategory> categories = new HashedSet<VideoCategory>();

    public VideoFolder()
    {

    }

    public VideoFolder(string path)
    {
        Path = path;
    }

    public string Path { get; set; }
    public string Name { get; private set; }

    public IEnumerable<VideoCategory> Categories { get { return categories; } }

    protected internal void AddCategory(VideoCategory videoCategory)
    {
        Contract.Requires(videoCategory != null);

        categories.Add(videoCategory);
    }

    protected internal void RemoveCategory(VideoCategory videoCategory)
    {
        categories.Remove(videoCategory);
    }
}

public class VideoCategoryMap : ClassMap<VideoCategory>
{
    public VideoCategoryMap()
    {
        Table("VideoCategories");

        Id(cat => cat.Id)
            .GeneratedBy.Native();

        Map(cat => cat.Name)
            .Unique()
            .Not.Nullable();

        HasManyToMany<VideoFolder>(Reveal.Member<VideoCategory>("folders"))
            .Access.CamelCaseField()
            .AsSet()
            .Inverse()
            .Cascade.AllDeleteOrphan();
    }
}

public class VideoFolderMap : ClassMap<VideoFolder>
{
    public VideoFolderMap()
    {
        Table("VideoFolders");

        Id(folder => folder.Id)
            .GeneratedBy.Native();

        Map(folder => folder.Path)
            .Not.Nullable();

        HasManyToMany<VideoCategory>(Reveal.Member<VideoFolder>("categories"))
            .Access.CamelCaseField()
            .AsSet();
    }
}

tengo estos 2 unidad de pruebas:

[Fact]
public void DeletingVideocategory_DeletesVideoFolders()
{
    object id;

    using (ISession session = SessionFactory.OpenSession())
    {
        var categ = new VideoCategory("Foo");
        var folder = new VideoFolder("D:\\Foo");
        categ.AddFolder(folder);

        id = session.Save(categ);

        session.Flush();
    }

    using (ISession session = SessionFactory.OpenSession())
    {
        var category = session.Get<VideoCategory>(id);
        category.ClearFolders();

        session.Delete(category);
        session.Flush();

        Assert.Equal(0, session.QueryOver<VideoFolder>().RowCount());
    }
}

[Fact]
public void DeletingVideocategory_DoesntDeleteVideoFoldersOwned_ByOtherCategories()
{
    object id;
    object id2;

    using (ISession session = SessionFactory.OpenSession())
    {
        var categ = new VideoCategory("Foo");
        var categ2 = new VideoCategory("Bar");
        var folder = new VideoFolder("D:\\Foo");

        categ.AddFolder(folder);
        categ2.AddFolder(folder);

        id = session.Save(categ);
        id2 = session.Save(categ2);

        session.Flush();
    }

    using (ISession session = SessionFactory.OpenSession())
    {
        var category = session.Get<VideoCategory>(id);
        category.ClearFolders();

        session.Delete(category);
        session.Flush();

        Assert.Equal(1, session.QueryOver<VideoFolder>().RowCount());
        Assert.Equal(1, session.Get<VideoCategory>(id2).Folders.Count());
    }
}

La primera de ellas tiene éxito, pero no la primera aserción de la segunda, donde se elimina la carpeta de vídeo, mientras que todavía se asocia con la categoría de video restante.

Aquí está la salida de SQL de la segunda prueba:

INSERT INTO VideoCategories (Name) VALUES (@p0); select last_insert_rowid();@p0 = 'Foo' [Type: String (0)]
INSERT INTO VideoFolders (Path) VALUES (@p0); select last_insert_rowid();@p0 = 'D:\Foo' [Type: String (0)]
INSERT INTO VideoCategories (Name) VALUES (@p0); select last_insert_rowid();@p0 = 'Bar' [Type: String (0)]
INSERT INTO CategoriesToFolders (VideoFolder_id, VideoCategory_id) VALUES (@p0, @p1);@p0 = 1 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]
INSERT INTO CategoriesToFolders (VideoFolder_id, VideoCategory_id) VALUES (@p0, @p1);@p0 = 1 [Type: Int32 (0)], @p1 = 2 [Type: Int32 (0)]
SELECT videocateg0_.Id as Id10_0_, videocateg0_.Name as Name10_0_ FROM VideoCategories videocateg0_ WHERE videocateg0_.Id=@p0;@p0 = 1 [Type: Int32 (0)]
SELECT folders0_.VideoCategory_id as VideoCat1_1_, folders0_.VideoFolder_id as VideoFol2_1_, videofolde1_.Id as Id13_0_, videofolde1_.Path as Path13_0_ FROM CategoriesToFolders folders0_ left outer join VideoFolders videofolde1_ on folders0_.VideoFolder_id=videofolde1_.Id WHERE folders0_.VideoCategory_id=@p0;@p0 = 1 [Type: Int32 (0)]
SELECT categories0_.VideoFolder_id as VideoFol2_1_, categories0_.VideoCategory_id as VideoCat1_1_, videocateg1_.Id as Id10_0_, videocateg1_.Name as Name10_0_ FROM CategoriesToFolders categories0_ left outer join VideoCategories videocateg1_ on categories0_.VideoCategory_id=videocateg1_.Id WHERE categories0_.VideoFolder_id=@p0;@p0 = 1 [Type: Int32 (0)]
SELECT videos0_.VideoFolder_id as VideoFol3_1_, videos0_.Id as Id1_, videos0_.Id as Id12_0_, videos0_.Path as Path12_0_ FROM VideoFiles videos0_ WHERE videos0_.VideoFolder_id=@p0;@p0 = 1 [Type: Int32 (0)]
DELETE FROM CategoriesToFolders WHERE VideoFolder_id = @p0;@p0 = 1 [Type: Int32 (0)]
DELETE FROM VideoFolders WHERE Id = @p0;@p0 = 1 [Type: Int32 (0)]
DELETE FROM VideoCategories WHERE Id = @p0;@p0 = 1 [Type: Int32 (0)]
SELECT count(*) as y0_ FROM VideoFolders this_

Si cambio de la asignación, y modificar Cascade.AllDeleteOrphan en VideoCategoryMap, la segunda prueba tiene éxito, mientras que la primera falla, debido a que la carpeta de vídeo huérfanos no se elimina.

¿Cómo puedo hacer ambas pruebas para tener éxito?

Gracias de antemano

Mike

¿Fue útil?

Solución

"huérfanos Borrar" en NHibernate no significa "entidades borrar sin otros padres". Significa "cuando se elimina la relación, elimine la entidad referenciada también".

NHibernate no maneja el caso de que usted necesita OOTB. Posibles soluciones incluyen lógica de nivel de dominio, la lógica de nivel repositorio, los detectores de eventos y factores desencadenantes.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top