I have two classes:
public partial class ObjectiveDetail {
public ObjectiveDetail() {
this.SubTopics = new List<SubTopic>();
}
public int ObjectiveDetailId { get; set; }
public int Number { get; set; }
public string Text { get; set; }
public virtual ICollection<SubTopic> SubTopics { get; set; }
}
public partial class SubTopic {
public int SubTopicId { get; set; }
public string Name { get; set; }
}
I have an ObjectiveDetail object from the user:
var web = {
"objectiveDetailId":1,
"number":1,
"text":"datafromweb",
"subTopics":[
{"subTopicId":1,
"name":"one"
},
{"subTopicId":3,
"name":"three",
}
]
}
And an ObjectiveDetail from the database:
var db = {
"objectiveDetailId":1,
"number":1,
"text":"datafromdb",
"subTopics":[
{"subTopicId":1,
"name":"one"
},
{"subTopicId":2,
"name":"two",
}
]
}
With Entity Framework 6 I know I can update the text in the ObjectiveDetail class using:
_uow.ObjectiveDetails.Update(web));
But how can I update the references to ObjectiveDetail and SubTopics in the many to many table that joins these two table. Here for example I would want it so that for ObjectiveDetail 1 the many-many is changed to reference subTopicId 1 and 3 instead of the values 1 and 2. Note that ObjectiveDetail and SubTopic are stored in tables with another table between them. Here's the DDL:
CREATE TABLE [dbo].[ObjectiveDetail] (
[ObjectiveDetailId] INT IDENTITY (1, 1) NOT NULL,
[Text] NVARCHAR (MAX) NOT NULL,
[ObjectiveTopicId] INT NULL,
CONSTRAINT [PK_ObjectiveDetail] PRIMARY KEY CLUSTERED ([ObjectiveDetailId] ASC),
);
CREATE TABLE [dbo].[ObjectiveTopic] (
[ObjectiveDetailId] INT NOT NULL,
[SubTopicId] INT NOT NULL,
CONSTRAINT [FK_ObjectiveTopicObjectiveDetail] FOREIGN KEY ([ObjectiveDetailId]) REFERENCES [dbo].[ObjectiveDetail] ([ObjectiveDetailId]),
CONSTRAINT [FK_ObjectiveTopicSubTopic] FOREIGN KEY ([SubTopicId]) REFERENCES [dbo].[SubTopic] ([SubTopicId])
);
CREATE TABLE [dbo].[SubTopic] (
[SubTopicId] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (150) NOT NULL,
CONSTRAINT [PK_SubTopic] PRIMARY KEY CLUSTERED ([SubTopicId] ASC),
);
Here's the EF Mapping that I have:
public class ObjectiveDetailMap : EntityTypeConfiguration<ObjectiveDetail>
{
public ObjectiveDetailMap()
{
// Primary Key
this.HasKey(t => t.ObjectiveDetailId);
// Relationships
this.HasMany(t => t.SubTopics)
.WithMany(t => t.ObjectiveDetails)
.Map(m =>
{
m.ToTable("ObjectiveTopic");
m.MapLeftKey("ObjectiveDetailId");
m.MapRightKey("SubTopicId");
});
}
}
I've only used EF with Code first, and to define the 3 tables you either define all 3 tables or you just define the 2 tables with a collection in each like this
If you have the 3 tables, it's easy to just update the middle table with new ids. You have to get all the ObjectiveTopics that you wish to update, and change the ids, and then do the update
If you don't have the third table defined as an entity, and you only have access to ObjectiveDetail and SubTopic tables, then you can get a hold of both entities and remove the one you don't want anymore, and add the one that you want.
If you want to (and probably should), you can use linq on the objectiveD to get the entity from the collection instead of retrieving it from the database.
You could use a generic method, so that it can be used for any many to many relationship. You would just give this list of integers representing the IDs of the field you want to update in the many-to-many collection off your main object:
You would call it like this:
I think you are trying to simulating offline mode working for your users. So when you get something from your users, you want to sync database with user data. I make an example and take your question one step beyond :) I added a Subtopic which needs to be updated in database. Ok here is the code:
The result:
That's it. You can sync your database and user data like this. And also AutoMapper and ValueInjecter both are very useful and powerful tools, I deeply recommend you to take a look at those. I hope you enjoyed, happy coding :)
Here's a method that takes the target
ObjectiveDetail
's ID and anIEnumerable<int>
ofSubTopic
IDs that you want to add to the targetObjectiveDetail
.