question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add FK constraint checking to the in-memory provider

See original GitHub issue

Hi, my apologies if this is already covered by any other open/closed issue but I couldn’t find any. It seems that the In-memory provider is not enforcing required foreign key properties and thus acts differently from SQL Server provider. I’m using build 7.0.0-beta5-13171 (latest nightly).

I suppose this is a known issue? Is there a plan/target for fixing it? I believe unit testing is a big use case for using the in-memory provider but with this kind of limitations, its value is diminished (for now).

Here’s sample code to demonstrate this:

[TestMethod]
[ExpectedException(typeof(DbUpdateException))]
public void AddOnlyChild_SQL()
{
    /* This method throws an exception (as it should): 
     * Microsoft.Data.Entity.Update.DbUpdateException: An error occurred while updating the entries. 
     * See the inner exception for details. 
     * ---> System.Data.SqlClient.SqlException: 
     * The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Child_Parent_ParentId". 
     * The conflict occurred in database "EF7Test", table "dbo.Parent", column 'Id'.
     */
    using (var ctx = new SimpleContext())
    {
        AddOnlyChild(ctx);
    }
}

[TestMethod]
[ExpectedException(typeof(DbUpdateException))]
public void AddOnlyChild_InMemory()
{
    // this doesn't throw an exception, thus failing the test 
    var optionsBuilder = new DbContextOptionsBuilder();
    optionsBuilder.UseInMemoryStore();
    using (var ctx = new SimpleContext(optionsBuilder.Options))
    {
        AddOnlyChild(ctx);
    }
}

private static void AddOnlyChild(SimpleContext ctx)
{
    var child = new Child {Name = "Dave", Id = Guid.NewGuid()};
    ctx.Children.Add(child);
    ctx.SaveChanges();
}

Context & model:

public class SimpleContext : DbContext
{
    public SimpleContext() { }

    public SimpleContext(DbContextOptions options) : base(options)  { }

    public DbSet<Parent> Parents { get; set; }
    public DbSet<Child> Children { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
            optionsBuilder.UseSqlServer(@"Server=(localdb)\v11.0;Database=EF7Test;Trusted_Connection=True;MultipleActiveResultSets=true");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Child>().Table("Child");

        modelBuilder.Entity<Child>().Key(r => r.Id);

        modelBuilder.Entity<Child>()
            .Property(r => r.Id)
            .GenerateValueOnAdd(true);

        modelBuilder.Entity<Child>()
            .Reference<Parent>(rs => rs.Parent)
            .InverseCollection(r => r.Children)
            .ForeignKey(rs => rs.ParentId)
            .Required();

        // parent model

        modelBuilder.Entity<Parent>().Table("Parent");

        modelBuilder.Entity<Parent>().Key(r => r.Id);

        modelBuilder.Entity<Parent>()
            .Property(r => r.Id)
            .GenerateValueOnAdd(true);
    }
}

public class Parent
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public List<Child> Children { get; set; }
}

public class Child
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public Guid ParentId { get; set; }
    public Parent Parent { get; set; }
}

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:14
  • Comments:9 (6 by maintainers)

github_iconTop GitHub Comments

6reactions
SimonCroppcommented, Jun 20, 2018

so i needed to work around this enough times that i wrapped the workaround in a nuget https://github.com/SimonCropp/EfCore.InMemoryHelpers

6reactions
ajcvickerscommented, Aug 23, 2017

Based on the semantics of the FK as discussed in #9470 and that these semantics now matter for querying data from the in-memory provider, we think it would now be useful to have the in-memory provider check cosntraints–that is, if an FK has a non-null value, then there must be a principal key with that value.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Does EF Core In Memory Provider validates referential ...
Does EF Core In Memory Provider validates referential constraints? The answer is: No. InMemory provider is not a replacement for relational ...
Read more >
Why does In-Memory feature not support foreign keys?
Can anyone explain what the problem with foreign key relationships and in-memory is? I guess just and only this limitation alone may be...
Read more >
Create Foreign Key Relationships - SQL Server
FOREIGN KEY constraints can reference only tables within the same database on the same server.
Read more >
Migrate tables with a foreign key to memory-optimized ...
Method 1: Drop and re-create the foreign key. ... Let's drop the foreign keys named FK_Product from the tblOrder tables. ... Step 2:...
Read more >
Create and manage check constraints | Cloud Spanner
Adding a CHECK constraint to an existing table starts the enforcement of the constraint immediately for new data and starts a long-running operation...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found