Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it possible to turn the foreign key constraints off? #185

Open
azsdaja opened this issue Oct 15, 2019 · 11 comments
Open

Make it possible to turn the foreign key constraints off? #185

azsdaja opened this issue Oct 15, 2019 · 11 comments
Assignees

Comments

@azsdaja
Copy link

azsdaja commented Oct 15, 2019

I'm trying to write some integration tests for my system. I'm using Effort for keeping my persistence context in memory. However, since the data model of my system is huge and there are lots of consistency contraints on many tables, I have to prepare much more data than I need for the test case just to satisfy foreign key contraints. Thus I'd like to turn the foreign key check off. I'm aware this makes my in-memory model less consistent with the real model, but in most test cases taking responsibility for this will be better than struggling with making the model just work.

Or maybe there is already some way to do it?

@JonathanMagnan JonathanMagnan self-assigned this Oct 15, 2019
@JonathanMagnan
Copy link
Member

Hello @azsdaja ,

At first sight, it could maybe be possible to do such a request.

I cannot promise it yet but I will certainly take more time to investigate it this week before assigning this task to my developer if that's possible.

Best Regards,

Jonathan


Performance Libraries
context.BulkInsert(list, options => options.BatchSize = 1000);
Entity Framework ExtensionsEntity Framework ClassicBulk OperationsDapper Plus

Runtime Evaluation
Eval.Execute("x + y", new {x = 1, y = 2}); // return 3
C# Eval FunctionSQL Eval Function

@JonathanMagnan
Copy link
Member

Hello @azsdaja ,

We started this request but my developer asked me if you could provide him a sample project.

The reason for this project is to make sure we will support your case since:

  • We can do something on Effort side about constraint
  • We cannot do anything on EntityFramework side when they are validating the constraint

So we want to make sure the code we will develop will work on your scenario

@azsdaja
Copy link
Author

azsdaja commented Oct 16, 2019

Thanks for taking my request into consideration. I'll attach a snippet tomorrow.

@JonathanMagnan
Copy link
Member

Hello @azsdaja

Since our last conversation, we haven't heard from you.

Would it be possible to provide ys a sample project?

Looking forward to hearing from you,

Jon

@azsdaja
Copy link
Author

azsdaja commented Oct 22, 2019

Sorry for delay, I was busy unfortunately. But I'm still interested in this issue. I'm hoping to provide the project tomorrow. Otherwise feel free to close the issue and if I have the project later, I'll reopen it.
Thank you.

@JonathanMagnan
Copy link
Member

Awesome!

Don't worry, we all have unexpected tasks along our way!

We will leave it open for another week!

Looking forward to hearing from you,

Jon

@azsdaja
Copy link
Author

azsdaja commented Oct 31, 2019

EffortAndIntegrationTests.zip
Finally I found some time for it. Here it is. The data hierarchy is basic, but it presents the problem.

@JonathanMagnan
Copy link
Member

Awesome,

We will look at it ;)

@RyanMarcotte
Copy link

Has any progress been made on this? I'm guessing no.

@RyanMarcotte
Copy link

RyanMarcotte commented Jan 12, 2023

I figured out a workaround. Entity Framework provides the ability to ignore database models in its OnModelCreating method via the ModelBuilder.

public class SampleDbContext : DbContext, IDbModelCacheKeyProvider
{
    private readonly SampleDbContextTestConfiguration_IncludedTypeCollection _testConfiguration = null;

    // .. other constructors set CacheKey = "production"

    // new constructor used only for testing purposes
    // use InternalsVisibleTo assembly attribute to access this constructor in tests
    internal SampleDbContext(DbConnection dbConnection, SampleDbContextTestConfiguration_IncludedTypeCollection configuration)
        : base(dbConnection, false)
    {
        if (!IsInMemoryDatabase(dbConnection))
            throw new InvalidOperationException("Expected database connection to in-memory database supplied by Effort!");

        _testConfiguration = configuration ?? throw new ArgumentNullException(nameof(configuration));
        
        // https://stackoverflow.com/questions/46035249/how-to-force-fire-onmodelcreating-every-datacontext-initialized-up
        CacheKey = String.Join("|", configuration.Select(type => type.Name).OrderBy(typeName => typeName));
    }

    // ... all your DbSet properties
    
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // ... other model configurations

        IgnoreDatabaseModelsForTesting(modelBuilder);
    }

    private void IgnoreDatabaseModelsForTesting(DbModelBuilder modelBuilder)
    {
        if (_testConfiguration == null)
            return;

        // use reflection to retrieve all database model types referenced by the context
        // likely need to do something different for your database context unless all database models inherit from a base type
        var dbModelTypeCollection = typeof(SampleDbContext).Assembly.GetTypes()
            .Where(t => typeof(DbModelBase).IsAssignableFrom(t) && !t.IsAbstract)
            .ToArray();

        // ignore all database models except for the ones included in the configuration
        // foreign key constraints will still be enforced across the included database model types
        modelBuilder.Ignore(dbModelTypeCollection.Except(includedTypeCollection));
    }
}
// new type to provide fluent interface for specifying database model types
public class SampleDbContextTestConfiguration_IncludedTypeCollection : IEnumerable<Type>
{
    private readonly ImmutableHashSet<Type> _allowedTypeCollection;

    public SampleDbContextTestConfiguration_IncludedTypeCollection()
    {
        _allowedTypeCollection = ImmutableHashSet<Type>.Empty;
    }

    private SampleDbContextTestConfiguration_IncludedTypeCollection(ImmutableHashSet<Type> typeCollection)
    {
        _allowedTypeCollection = typeCollection ?? throw new ArgumentNullException(nameof(typeCollection));
    }

    public SampleDbContextTestConfiguration_IncludedTypeCollection IncludingDbModel<T>() where T : class, DbModelBase
    {
        return new SampleDbContextTestConfiguration_IncludedTypeCollection(_allowedTypeCollection.Add(typeof(T)));
    }

    public IEnumerator<Type> GetEnumerator() => _allowedTypeCollection.GetEnumerator();
    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

@RyanMarcotte
Copy link

RyanMarcotte commented Feb 9, 2023

Ran into a snag related to model caching between test runs. Implementing IDbModelCacheKeyProvider on the DbContext did the trick. I've modified the sample above accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants