简体   繁体   中英

How to save relational entries in EF

I have 3 tables in my database.

1 called Images, 1 called Tags and the last table is called ImageTagIds

My Images table has ID and Path

My Tags has ID and Phrase

and my ImageTagIds has ID, ImageId and TagId

I'm hoping the names help to make this self explaining but there is a 1 to many relationship between Image table and ImageTagIds, where Image.ID joins on ImageTagIds.ImageId

There is a 1 to man relationship between Tag table and ImageTagIds where Tag.Id joins on ImageTagIds.Id

I added a database diagram in SSMS and created all the keys and relationships.

Within VS 2012, I create a new EF (.edmx) file, and add my tables. VS does something with witchcraft and I can now treat my tables as objects. This works great, I can query and save without exceptions.

The issue I have is creating the relationship.

This is how far I've got

    private Dal.MyEntities _dc = new MyEntities();

    public void Save(string filePath, IList<string> tags)
    {
        FileInfo fi = new FileInfo(filePath);

        this._dc.Images.Add(new Image()
        {
            Path = fi.DirectoryName
        });

        foreach (var tag in tags)
        {
            this._dc.Tags.Add(new Tag()
            {
                Phrase = tag
            });
        }

        _dc.SaveChanges();
    }

The above saves into the Tags table and the Image table but, the ImageTagIds table remains empty. I can see why, I never attempt to write to it, but this is where I am lost. I don't know what I can write/code to the ImageTagsId table.

More research led me to http://www.entityframeworktutorial.net/entity-relationships.aspx and this says (I think) EF should know where the relationships are. Even if it does, I don't know what/how I can save as I will not know what the ID's are going to be when I add new entries into the database.

You are adding tags and you are adding images but you are not adding tags to images.

Try the following

_dc.Images.FirstOrDefault().Tags.Add(new Tag() { Phrase = "something"});

From the perspective of entities this will add a tag to a particular image. From the perspective of db tables it will add the tag into the Tags table and ImageTagIds table.

EDIT : If you don't have a Tags property you should first ensure your database relations are properly made. If that is not the case you can try

TagsImagesIds tagImageRelation = new TagsImagesIds();
tagImageRelation.ImageId = image.Id;
tagImage.Relation.TagId = tag.Id;
_dc.TagsImagesIds.Add(tagImageRelation);

Typically the reason you are missing the Tags property in images is that you have more columns in your table other than TagId and ImageId so EF creates 3 classes to represent your tables instead of 2.

This is a many to many relationship, implemented with a junction table that has additional properties (and the definition of the key doesn't match with what EF expects for a many-to-many relationship). In this case EF treats the junction table as any other entity, so you have to create and save the entries to this table yourself. See note on many-to-may EF relationship at the bottom

Provided that your ImagetTagId has the following:

  • a relationship, an navigation property to Image
  • a relationship, and navigation property to Tag

and the ID is database generated (identity), then you simply have to create all the necessary ImageTagId objects and set the navigation properties. When you call SaveChanges the DbContext will do the relationship fixup, setting the correct Ids in the ImageTagId objects and saving them to the database.

It should be something like this:

    Image img = new Image()
    {
        Path = fi.DirectoryName
    };
    this._dc.Images.Add(img);

    foreach (var tag in tags)
    {
        Tag tag = new Tag()
        {
            Phrase = tag
        };
        this._dc.Tags.Add();
        ImageTagId = new ImageTagId { Image = image, Tag = tag };
        this._dc.ImageTagIds.Add(ImageTagId);
    }

Obviously what you cannot do is to set he Ids in the ImageTagId because they're not available until they are saved. That's way it's necessary to have the navigation properties to Tag and Image .

When you call SaveChanges the image is saved to the db, and get its db generated id. The same happens when saving each tag. And, when saving each ImageTagId , as it is related to a tag and an image which already have ids, EF copy those Ids, and save the "fixed-up" object to the DB. Read this on MSDN: Relationships and Navigation Properties , paying gspecial attention to the section Synchronizing the changes between the FKs and Navigation properties .

Many to many relationships in EF

If you want to define a pure many to many relationship on EF, you need a junction table that only has

  • an FK to one of the many to many sides
  • an FK to the other side
  • a PK which is composed of both FKs

In your particular case, you should have a table which only has an Id which is a FK to Image, another Id which is an FK to Tag, and a primary key composed of both FKs.

When you use an EF many to many relationship the junction table doesn't appear as an entiy in the model. Instead, you only have a navigation property from each side to a collection on the other side. In your particular side you'd have an Images collection on Tag and a Tags collection on Image.

If you impelement a many to many like this, the junction table entries will be automatically managed by EF.

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