简体   繁体   中英

EF many to many relationship is not adding records for one of the entities

So I'm following the book Entity Framework 6 Recipes . I am using Visual Studio 2017 , .NET 4.6.1 and EF 6.2.0 .

I've created this simple DB structure:

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)

and in the code I have this:

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

The problem is when I try to add new records to the database. If in the SeedMusicData() I have this:

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

then everything works fine and the data is stored in the database.

However if I try to do it like this:

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

Then nothing is stored in the database, I don't get some sort of exception either. And I think I'm following the book literally except for this one:

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

Since I was getting error which seemed to be caused by the lack of primary key for the junction table, and after adding one the error was fixed. But I wonder if this could be the cause of the problem.

PS

So some additional info:

This is how the model looks in VS designer:

音乐.edmx

And inside Music.tt I have:

Album.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; }
    }

And Artist.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; }
    }

The junction table is in the DataBase but from what I understand it's expected for EF to not include it if it only contains the two Foreign Keys.

In SeedMusicData, add artists to album instead of adding album to artist.

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

When you add album, it will also "bring" artists during SaveChanges.

UPDATE: if you want, you can check the State of your entities before SaveChanges:

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

If you add artists to the album, all the entries will be marked as "Added". If you add the album to artists, album entry will be marked as "Added" but artists entries will be marked as "Detached". Detached entries will be not processed by SaveChanges resulting in an incomplete database update.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM