代码之家  ›  专栏  ›  技术社区  ›  Leron

EF多对多关系未为其中一个实体添加记录

  •  0
  • Leron  · 技术社区  · 7 年前

    所以我在看这本书 Entity Framework 6 Recipes 。我正在使用 Visual Studio 2017 ,则, .NET 4.6.1 EF 6.2.0

    我创建了这个简单的DB结构:

    CREATE TABLE Album
    (
        AlbumId INT IDENTITY(1,1) NOT NULL,
        AlbumName NVARCHAR(100) NOT NULL,
        CONSTRAINT [PK_Album] PRIMARY KEY CLUSTERED ([AlbumId] ASC)
    )
    
    CREATE TABLE Artist
    (
        ArtistId INT IDENTITY(1,1) NOT NULL,
        FirstName NVARCHAR(100) NOT NULL,
        MiddleName NVARCHAR(100) NOT NULL,
        LastName NVARCHAR(100) NOT NULL,
        CONSTRAINT [PK_Artist] PRIMARY KEY CLUSTERED (ArtistId ASC)
    )
    
    CREATE TABLE LinkTable
    (
        ArtistId INT NOT NULL,
        AlbumId INT NOT NULL,
        CONSTRAINT FK_LinkTable_Artist FOREIGN KEY (ArtistId) REFERENCES dbo.Artist (ArtistId),
        CONSTRAINT FK_LinkTable_Album FOREIGN KEY (AlbumId) REFERENCES dbo.Album (AlbumId)
    )
    ALTER TABLE LinkTable ADD CONSTRAINT PK_LinkTable PRIMARY KEY (ArtistId, AlbumId)
    

    在代码中我有:

    static void Main(string[] args)
    {
        SeedMusicData();    
        ListMusicData();
    }
    

    问题是当我尝试向数据库添加新记录时。如果在 SeedMusicData() 我有这个:

    private static void SeedMusicData()
    {
        using (var context = new MusicEntities())
        {
            var artist = new Artist { FirstName = "Alan", LastName = "Jackson", MiddleName = "X." };
            var album1 = new Album { AlbumName = "Drive" };
            var album2 = new Album { AlbumName = "Live at Texas stadium" };
    
            artist.Albums.Add(album1);
            artist.Albums.Add(album2);
    
            context.Artists.Add(artist);
            context.SaveChanges();
        }
    }
    

    然后一切正常,数据存储在数据库中。

    但是,如果我尝试这样做:

    private static void SeedMusicData()
    {
        using (var context = new MusicEntities())
        {
            var artist1 = new Artist { FirstName ="Tobby", LastName = "Keith", MiddleName = "Y." };
            var artist2 = new Artist { FirstName = "Merle", LastName = "Haggard", MiddleName = "Z." };
            var album = new Album { AlbumName = "Hokytonk University"};
            artist1.Albums.Add(album);
            artist2.Albums.Add(album);
    
            context.Albums.Add(album); //use Albums instead Artists when it works
    
            context.SaveChanges();
        }
    }
    

    然后数据库中没有存储任何内容,我也没有遇到任何异常。我想除了这本书之外,我一直在遵循这本书:

    ALTER TABLE LinkTable ADD CONSTRAINT PK_LinkTable PRIMARY KEY (ArtistId, AlbumId)
    

    由于我得到的错误似乎是由于缺少连接表的主键引起的,在添加一个主键后,错误得到了修复。但我想知道这是否是问题的原因。

    P、 S

    因此,一些其他信息:

    这是模型在VS designer中的外观:

    Music.edmx

    和内部 Music.tt 我有:

    专辑cs:

    public partial class Album
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Album()
            {
                this.Artists = new HashSet<Artist>();
            }
    
            public int AlbumId { get; set; }
            public string AlbumName { get; set; }
    
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Artist> Artists { get; set; }
        }
    

    和艺术家。cs:

    public partial class Artist
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public Artist()
            {
                this.Albums = new HashSet<Album>();
            }
    
            public int ArtistId { get; set; }
            public string FirstName { get; set; }
            public string MiddletName { get; set; }
            public string LastName { get; set; }
    
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
            public virtual ICollection<Album> Albums { get; set; }
        }
    

    连接表在数据库中,但据我所知,如果它只包含两个外键,则EF应该不包含它。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Fabrizio Accatino    7 年前

    在SeedMusicData中,将艺术家添加到唱片集,而不是将唱片集添加到艺术家。

    album.Artist.Add(artist1);
    album.Artist.Add(artist2);
    context.Album.Add(album);    
    context.SaveChanges();
    

    当您添加相册时,它还会在保存更改期间“带来”艺术家。

    更新:如果需要,可以在保存更改之前检查实体的状态:

    var s1 = context.Entry(artist1).State;
    var s2 = context.Entry(artist2).State;
    var sx = context.Entry(album).State;
    

    如果将艺术家添加到相册,所有条目都将标记为“已添加”。如果将相册添加到艺术家,相册条目将标记为“已添加”,但艺术家条目将标记为“已分离”。SaveChanges不会处理分离的条目,从而导致数据库更新不完整。