Make it possible to turn the foreign key constraints off?
azsdaja opened this issue · 11 comments
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?
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 Extensions • Entity Framework Classic • Bulk Operations • Dapper Plus
Runtime Evaluation
Eval.Execute("x + y", new {x = 1, y = 2}); // return 3
C# Eval Function • SQL Eval Function
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
Thanks for taking my request into consideration. I'll attach a snippet tomorrow.
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
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.
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
EffortAndIntegrationTests.zip
Finally I found some time for it. Here it is. The data hierarchy is basic, but it presents the problem.
Awesome,
We will look at it ;)
Has any progress been made on this? I'm guessing no.
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();
}
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.