0

je les deux entités, avec leurs applications suivantes:Many-to-Many et cascades: problème avec les entités suppression

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(); 
    } 
} 

Je ces 2 tests unitaires:

[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()); 
    } 
} 

Le premier on réussit, mais pas le premier Assert de la seconde, où le dossier vidéo est supprimé, alors qu'il est toujours associé à la catégorie vidéo restante.

Voici la sortie de SQL du second test:

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 [email protected];@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 [email protected];@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 [email protected];@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 [email protected];@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 je change la cartographie et de modifier Cascade.AllDeleteOrphan dans VideoCategoryMap, le second test réussit, alors que le premier échoue, car le dossier vidéo rendus orphelins n'est pas supprimé.

Comment puis-je réussir les deux tests?

Merci à l'avance

Mike

+0

Quel est exactement le problème avec le deuxième test unitaire? Laquelle des deux affirmations échoue? – Aaronontheweb

+0

Dans le deuxième test, c'est le premier assert qui échoue. Je suis en train de mettre à jour la question – Mike

Répondre

2

"Supprimer orphelin" dans NHibernate ne signifie pas "Supprimer des entités sans autres parents". Cela signifie "lors de la suppression de la relation, supprimez également l'entité référencée". NHibernate ne gère pas le cas où vous avez besoin d'OOTB. Les solutions possibles comprennent la logique au niveau du domaine, la logique au niveau du référentiel, les écouteurs d'événements et les déclencheurs.

+0

Donc, la manière correcte de faire cela serait de mapper les entités de sorte que seules les données de la table many-to-many soient supprimées, et supprimer manuellement les "entités sans parent"? – Mike

+0

Oui. Comme dit, vous pouvez automatiser cela de différentes manières; un déclencheur n'est pas une mauvaise idée. –

+0

Merci beaucoup, je vais jeter un oeil à cela – Mike