문제

So I have two tables, one has several foreign keys that all point to another table.

Example:

 TableA
 Id | FirstId | SecondId | ThirdId
 1  | 10      | 11       | 12
 2  | 13      | 14       | 15

And

 TableB
 Id | Value
 10 | 'Cat'
 11 | 'Dog'
 12 | 'Rabbit'
 13 | 'Bird'
 14 | 'Hamster'
 15 | null

Now when I build a query such as:

 var entity = context.TableA
     .Include(a => a.First)
     .Include(a => a.Second)
     .Include(a => a.Third)
     .SingleOrDefault(a => a.Id == 1)

Now depending on how I build the query I can get roughly one of two results back. If I go with the example from above I will get an an entity back, but SecondId might be 11 and have all of the correct properties set, but FirstId and ThirdId might have a value of 15 and all of the properties will be null (the Id is random but consistent and always the same for all queries, until I rebuild the database). Now if I replace the SingleOrDefault(...) with:

 .With(a => a.Id == 1).SingleOrDefault()

I will get back an entity with a FirstId, SecondId, and ThirdId of 10, 11, 12, respectively (correct), but only a.Second will have any properties set. a.First.Value and a.Third.Value will both be null. Also, it's always SecondId that is correct, never First or Third.

So my question is, does EntityFramework not support the idea of a single table having multiple relationships to another table, or is there something I'm missing, or?

I've tried inspecting the query generated by LINQ but when I run it against the database I get all of the correct values back. I've tried changing how I build the LINQ query and I've swapped between using .Include(...) and .Load(). When I used .Load() the incorrect Ids (15 in my first example) would actually propagate back to the database every time I would call .SaveChanges(), even if I did nothing but:

 using(MyDatabase context = new MyDatabase())
 {
      context.TableB.Load();
      context.SaveChanges();
 }

I'm using EntityFramework 6 and a SqlCE 4.0 database.

Classes for TableA & TableB (note these are auto generated from a edmx model):

public partial class TableA
{
    public int Id { get; set; }
    private int FirstId { get; set; }
    private int SecondId { get; set; }
    private int ThirdId { get; set; }

    public virtual TableB First { get; private set; }
    public virtual TableB Second { get; private set; }
    public virtual TableB Third { get; private set; }
}

public partial class TableB
{
    public int Id { get; set; }
    public string Value { get; set; }
}

I've also now tried switching the provider from System.Data.SqlServerCe.4.0 to System.Data.SqlClient (and also moving the database to a SQLExpress instance) and I get the same results.

도움이 되었습니까?

해결책 2

So I feel like an idiot, but I actually found the problem. There was another partial class from before I started to upgrade to use EntityFramwork:

public partial class TableA
{
    public static readonly TableB DefaultTableBValue = new TableB(null);

    public TableA()
    {
        this.First = TableA.DefaultTableBValue;
        this.Second = TableA.DefaultTableBValue;
        this.Third = TableA.DefaultTableBValue;
    }
}

public partial class TableB
{
    public TableB(string value)
    {
        this.Value = value;
    }
}

This would apparently confuse EntityFramework's object mapper, and when it would instantiate a new object (before it was returned from the database) it would see the First, Second and Third values change and either try and commit those back to the database or it would not copy over the 'default values' and just return the object as is. As soon as I removed this unneeded partial class, everything worked flawlessly.

Long story short, be careful creating default constructors and modifying any of the database properties. EntityFramework doesn't seem to know what to do when it detects the value changing in the constructor.

다른 팁

I think there is a bit bug on generated classes. Could you please try changing TableA like below and then try again?

public class TableA
{
    public int Id { get; set; }
    [ForeignKey("First")]
    private int? FirstId { get; set; }
    [ForeignKey("Second")]
    private int? SecondId { get; set; }
    [ForeignKey("Third")]
    private int? ThirdId { get; set; }

    public virtual TableB First { get; private set; }
    public virtual TableB Second { get; private set; }
    public virtual TableB Third { get; private set; }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top