Reputation: 8461
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.
Upvotes: 0
Views: 94
Reputation: 39055
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:
Image
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
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.
Upvotes: 1
Reputation: 2037
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.
Upvotes: 1