Entity framework core: How to test navigation propery loading when use in-memory datastore
Asked Answered
B

1

5

There is an interesting feature exists in entity framework core:

Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

This is nice in some cases. However at the current moment I'm trying to modelling many-to-many relation with advanced syntaxic additions and wan't to check, that the mapping I create work well.

But I actually can't do that, since if let's say I have something like:

class Model1{
   ... // define Id and all other stuff
   public ICollection<Model2> Rel {get; set;}
}

Model1 m1 = new Model1(){Id=777};
m1.Rel.Add(new Model2());
ctx.Add(m1);
ctx.SaveChanges()

var loaded = ctx.Model1s.Single(m => m.Id == 777);

so due to auto-fixup loaded.Rel field already will be populated, even if I don't include anything. So with this feature I can't actually check nothing. Can't check that I use proper mapping, and my additions to Include works properly. Having thouse in mind, what should I change to be able to actaully test my navigation properties work properly?


I create a testcase which should be passing, but now failing. Exact code could be found there

I'm using .Net Core 2.0 preview 1 and EF core according to that.

Bohman answered 1/6, 2017 at 0:15 Comment(6)
You can create a new DbContext which has no entities created and do the second query on it, though you need to inject it's DbContextOptions and pass it to its constructorRank
Yes. I tryed that. But seems like when using inmemory datastore when you create new DbContext it's create completelly clean inmemory store (even if the name of DB in options placed the same), so in new context there is no previously saved data and this fact once again not allow to test anything.Bohman
@Rank I added actual faling case into the question body, so you could check, if I'm doing something wrong.Bohman
Navigation is fixed up because dependent entities are being tracked in the context. Since you are using the same context which saves them that happens. You need to isolate you testing code from your setup code.Deery
@Deery How this possible? when creating new context - it's not contains any data. I mean in principe. newCtx.Models1 is empty for new context in inmemory case. at least for me, maybe I'm doing something wrong.Bohman
One possible error happens causing this is shared DbContext. DbContext is not thread safe. A bad setup in DI can put you in such state. I see you have linked code. I will test out. One possible error I see is using both UseInMemoryDatabase & AddEFInMemoryStore. You should not have both used together.Deery
R
8

If you want to test navigation properties with in-memory data store, you need to load your items in "non-tracked" mode, using AsNoTracking() extension.

So, for your case if var loaded = ctx.Model1s.Single(m => m.Id == 777); return you item with relations, than if you rewrite to:
var loaded = ctx.Model1s.AsNoTracking().Single(m => m.Id == 777); this will return you raw item without deps.

So then if you want to check Include again, you could write something like ctx.Model1s.AsNoTracking().Include(m => m.Rel).Single(m => m.Id == 777); and this will return you model with relations you include.

Rasheedarasher answered 1/6, 2017 at 11:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.