Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF Seed多对多相关表_C#_Entity Framework - Fatal编程技术网

C# EF Seed多对多相关表

C# EF Seed多对多相关表,c#,entity-framework,C#,Entity Framework,我有以下简化的多对多相关模型: public class Singer { [Key] public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Song> Songs { get; set; } } public class Song { [Key] public int Id { get; set; }

我有以下简化的多对多相关模型:

public class Singer
{
    [Key]
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Song> Songs { get; set; }
}

public class Song
{
    [Key]
    public int Id { get; set; }

    public string Title { get; set; }

    public virtual ICollection<Singer> Singers { get; set; }
}
我使用以下种子代码将项添加到已填充的表中,同时防止重复:

public static void SeedNewSingerAndSong(AppContext context)
{
    // Create new song
    Song newSong = new Song() { Title = "New Song" };

    context.Songs.AddOrUpdate(
        item => item.Title,
        newSong
    );

    context.SaveChanges();

    // Create new Singer
    Singer newSinger = new Singer() { Name = "New Singer" };

    context.Singers.AddOrUpdate(
        item => item.Name,
        newSinger
    );

    context.SaveChanges();
}
最近,我更新了种子代码,将“新歌手”链接到“现有歌曲”和“新歌”,如下所示:

public static void SeedNewSingerAndSong(AppContext context)
{
    // Create new song
    Song newSong = new Song() { Title = "New Song" };

    context.Songs.AddOrUpdate(
        item => item.Title,
        newSong
    );

    context.SaveChanges();

    // Find existing songs
    Song foundExistingSong = context.Songs.Single(x => x.Title == "Existing Song");
    Song foundNewSong = context.Songs.Single(x => x.Title == "New Song");

    // Create new Singer
    Singer newSinger = new Singer() { Name = "New Singer" };

    // Assign songs to new Singer
    newSinger.Songs.Add(foundExistingSong);
    newSinger.Songs.Add(foundNewSong);

    context.Singers.AddOrUpdate(
        item => item.Name,
        newSinger
    );

    context.SaveChanges();
}
这不起作用(没有关系被添加),可能是因为“新歌手”之前已经被添加了。如果我手动删除“New Singer”,则在播种时该歌手将与关系一起添加。但是,我不想删除项目只是为了添加关系。我该如何让这个种子工作


更新:当“新歌”在播种之前已经存在时,重复“新歌”的问题已通过更新的代码修复。

您还需要将歌手添加到歌曲中。这两个列表都列出了歌手。歌曲和歌曲。歌手需要由您的代码维护

public static void SeedNewSingerAndSong(AppContext context)
{
    ...

    // Assign songs to new Singer
    newSinger.Songs.Add(foundExistingSong);
    newSinger.Songs.Add(foundNewSong);

    // Assign Singer to Songs
    foundExistingSong.Singers.Add(newSinger);
    foundfoundNewSong.Singers.Add(newSinger);

    // The following duplicates "New Song" as explained in *Additional Info
    context.Singers.AddOrUpdate(
        item => item.Name,
        newSinger
    );

    context.SaveChanges();
}

重复发行:

实体框架不会跟踪新闻歌曲,因此不会与数据库中的任何现有记录关联。当它被添加到newSinger时,它被视为一条新记录,并被分配了一个新id(主键)。因此,你似乎得到了新闻歌曲的副本

要修复此问题,您需要对newSong进行跟踪,以便EF将其与其基础记录相关联。在这种情况下,您可以使用:

context.Attach(新闻歌曲)

通常,将跟踪查询检索到的实体。e、 g:

Song newSong=context.Songs.Single(x=>x.Title==“新歌”)

关于关系问题:

并指示AddOrUpdate不更新关系。一种解决方案是单独更新关系,而另一种解决方案是显式声明所有添加实体的主键值。我怀疑后者也会消除重复问题

您可以尝试以下方法:

var newSinger = context.Singers.Include("Songs").Single(x => x.Name == "New Singer");
newSinger.Songs.Clear();
newSinger.Songs = new List<Songs>{ foundNewSong, foundExistingSong };
context.SaveChanges();
var newSinger=context.Singers.Include(“歌曲”).Single(x=>x.Name==“新歌手”);
newSinger.Songs.Clear();
newSinger.Songs=新列表{foundNewSong,foundExistingSong};
SaveChanges();

为了提供更多的背景信息,
AddOrUpdate
所做的远远少于其名称所暗示的

  • 该方法查明实体是否存在。如果未添加,则将其标记为添加的
    ;如果是,则将其标记为
    已修改
    。但是,尽管标记为添加的
    也将嵌套实体标记为添加的
    ,标记为修改的
    仅将实体本身标记为修改的
    ,并且仅标记其标量属性,即不标记其关联

  • 它有一个恼人的问题:如果它找到一个现有实例,它将停止跟踪代码中可见的实例,并开始跟踪内部(不可见)实例。代码中对实例的任何后续更改都将被忽略

  • 简而言之:它适用于添加或更新独立实体,而不适用于相关实体。我认为不可避免的结论是:不要使用
    AddOrUpdate
    来种子化相关实体


    (就我个人而言,我会更进一步,不再使用它,句号)。

    你能发布DB模型吗?@Mikkk相关模型已经发布在顶部。底层表呢?你确定在调用AddOrUpdate(newSong)后会跟踪新闻歌曲吗?或者换句话说,是在调用AddOrUpdate(newSong)还是调用AddOrUpdate(newSinger)时创建的副本?是否可以确认跟踪是问题所在?您能否在将新闻歌曲添加到newSinger之前从数据库中检索新闻歌曲进行测试?@Mikkk非常感谢您的建议。一些显示如何最好地改进代码的代码会很有帮助。非常有意义。稍后我会尝试一下。为了澄清,我需要先添加或更新()没有相关歌曲的新歌手,然后再添加歌曲?但是为什么要使用Clear()?是的,添加或更新新歌手,然后添加歌曲。你是对的,不需要清除。我从其他代码中复制了这个示例,并在没有正确检查的情况下对其进行了修改。您可以使用“清除”保存创建新列表并添加项目。
    var newSinger = context.Singers.Include("Songs").Single(x => x.Name == "New Singer");
    newSinger.Songs.Clear();
    newSinger.Songs = new List<Songs>{ foundNewSong, foundExistingSong };
    context.SaveChanges();