mardi 28 juillet 2015

Use PK instead of object references im many-to-many associations with Entity Framework 6

I'm using EF6 and SQLite to cache API responses. So I have datamodels which are used both as models for Json.NET and as entities models for EF6. On 1:1 and 1:n associations all works fine, but I have problem on n:m associations, because EF6 identifies these associations using object references instead of primary keys of objects.

I created simple example for better derscribing of my problem:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

public class Student
{
    [Key]
    [JsonProperty("id")]
    public int Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonPropety("courses")]
    public List<Course> Courses { get; set; }
}

public class Course
{
    [Key]
    [JsonProperty("id")]
    public int Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonIgnore]
    public List<Student> Students { get; set; }
}

JSON API response with list of students:

{[
   { 
     "id": 1
     "name": "Paul",
     "courses": [
       { 
         "id": 1
         "name": "Course A"
       },
       { 
         "id": 2
         "name": "Course B"
       }
     ]
   },
   { 
     "id": 2
     "name": "John",
     "courses": [
       { 
         "id": 1
         "name": "Course A"
       }
     ]
   }
]}

So after deserializing, Course A in Paul's list is different instance from Course A instance in John's list. But logically these objects are same.

After I add these Students into DbContext.DbSet it fails, because EF6 is trying to add a "Course A" entity into the Courses table twice with same primary key. After I manually changed reference of Course A in John's collection to point to the Paul's Course A, it worked fine - entries are created in the StudentCourses join table.

So, my questions are:

1) Is there a way to set Json.NET to use same instance for value-equal objects (after overriding Equals and ==)?

2) Is there a way to force EF6 to use PK properties as identifiers of relationships?

3) Is there any better pattern to handle my problem?

Aucun commentaire:

Enregistrer un commentaire