Circular dependency when generating dbcontext migrations into another assembly - c#

As the name suggests I have multiple projects, and one of the project contains the dbcontext and all the models. So, I want to generate migrations from that project and put all generated migrations into another assembly (because I have multiple db providers for the same dbcontext, and one way is to move all migrations in different assemblies, so, i dont have problems later.).
Project containing the dbcontext and other stuff is not my main project, is just a class library.
The structure of the solution looks like below:
MyProject.DbContext
MyProject.DbContext.Migrations
MyProject
So, I reference the project MyProject.DbContext.Migrations from MyProject.DbContext to make the dotnet ef ... work, and I run this command:
dotnet ef migrations add InitMySql --project ..\MyProject.DbContext.Migrations
This will work fine as long as I do sth like this:
optionsBuilder.UseLazyLoadingProxies().UseMySql(configuration.ConnectionString, ServerVersion.AutoDetect(configuration.ConnectionString), builder =>
{
builder.CommandTimeout(configuration.CommandTimeout);
builder.UseNewtonsoftJson();
builder.MigrationsAssembly("MyProject.DbContext.Migrations");
});
But, now I have a big problem, the project MyProject.DbContext.Migrations needs also reference to MyProject.DbContext because of the new class created 'MyDbContextModelSnapshot' which has an attribute at the top: [DbContext(typeof(MyDbContext))] etc. Now I run into a circular dependency issue!
How is this supposed to be solved ?
I am currently using Asp.Net core 5, but I think this will happen for any version, seems more like a design limitation...

Related

How can I use a DbContext from a different assembly for my migrations?

I have multiple projects in a solution. For clean architecture reasons, I want to keep the DbContext in Infrastructure project, but my Startup Project is the API project. So the Program.cs is in the API project.
I tried to specify that I wanted to use my context from the Infrastructure proect like this:
builder.Services.AddDbContext<DzbcDbContext>(opt => opt.UseSqlServer(
builder.Configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly("DZBC.Infrastructure") )); // <- tried this
But it's not working. The error still tells me it's looking for the DbCOntext in the API project.
All similar answers are either old or don't work in .net core 6.
It's solved by forcing it in Developer PowerShell.
Navigate to the project folder where you have your DbContext (in my case Infrastructure). From there use this:
dotnet ef migrations add initial --startup-project "../DZBC.API/DZBC.API.csproj"
dotnet ef database update --startup-project "../DZBC.API/DZBC.API.csproj"
But use the .csproj path of your Startup project.

Using a separate migration project for F# data layer

I'm trying to setup migrations for my EF Core project on F# .NET 4.7.2. Currently I have the following data context:
type MyContext =
inherit DbContext
new() = { inherit DbContext() }
new(options: DbContextOptions<MyContext>) = { inherit DbContext(options) }
[<DefaultValue>]
val mutable apples: DbSet<AppleEntity>
member x.Apples
with get () = x.apples
and set v = x.apples <- v
Setting up my initial migration using Add-Migration Initial -Context Application.MyContext told me that F# is not a supported language for generating migrations, which is why I set up a C# project with a reference to the F# project.
However, when running the add migration command from this project, EF Core cannot find my context class: No DbContext named 'Application.MyContext' was found.
On Microsofts documentation about using a separate migration project, the following tip is stated:
If you have no existing migrations, generate one in the project containing the DbContext then move it. This is important because if the migrations assembly does not contain an existing migration, the Add-Migration command will be unable to find the DbContext.
But this is not a possibility for me, given that the context is in an F# project. Anyone have a clue on where to go from here?
EF is not F# friendly and AFAIK it's not in their near plan to improve the support for other languages. If you need migrations you have to use another framework like DbUp or another ORM like Linq2DB, Dapper. Easier option is to define the data layer in C# and reference it from other F# project
I managed to work around the issue by creating a C# version of MyContext and running the Add-Migration command. Then I deleted it and changed the reference in both MyContextModelSnapshot.cs and Initial.designer.cs to my F# data context.

How to use Code First Migrations When Domain Models in Separate Project from WebUI?

I have a VS 2017 solution with 2 .Net Core 1.1 projects, 1 is just a class library containing all of my domain models and the other is the actual MVC web application containing the contexts (the ApplicationDbContext & one I created) & all of the EFCore assemblies. I'm trying to enable & use migration on the context I created but having trouble being that the context is in the WebUI project and the models are in the class project. Upon 1st execution of Add-Migration command, I got this error about my target project didn't match my migrations assembly, so I figured out how to get around that by changing the migration assembly in Startup.cs. Add-Migration ended up working but the migration file was created in the class project where the EFCore assemblies are not referenced, thus giving an error on the migration file. I thought maybe I'd try and trick it by moving the file to my WebUI project to update the database, but then figured that may not work & there has to be an easier way of doing this. Does anyone know how to setup code first migrations for EFCore to keep track of modifications and update the database when my domain models are in another project? Any help would be greatly appreciated. Hopefully this isn't too vague. If more info is needed, I'll be all too happy to post. Thanks.
I may not be understanding the question correctly, but have you tried referencing your domain project in your webUI?

EF7 migration generator is ignoring context parameter

I have recently migrated my EF7 project from DotNet Core 1.0.0 to Version 1.1.0, now I have trouble with creating the database migrations.
In my project I have multiple contexts, the tool dotnet-ef is providing a command line parameter to distinct between these contexts in order to create a separate migration for each context.
When I try to create the migrations for the context "AuditLogContext" with the command
dotnet ef migrations add Initial --context 'Some.Namespace.AuditLogContext' --output-dir './Migrations/AuditLogMigrations'
then it fails, telling me
The name 'Initial' is used by an existing migration.
when I'm trying to create the migration with another name, say Initial2, the migration get created but for the wrong context.
In the folder
./Migrations/AuditLogMigrations
are new files named
20170212122451_Initial2.cs
20170212122451_Initial2.Designer.cs
CoreContextModelSnapshot.cs
I expect the file AuditLogContextModelSnapshot.cs instead.
Does anybody have solved this issue before?
I found the reason for this problem.
I have multiple contexts in my project, every context expects parameters. So migrations builder expects a factory for every context.
In my case one class, implements all factories, now there is a bug that the concrete order of the interfaces is used to determine which migrations are created.
public class Program : IDbContextFactory<CoreContext>, IDbContextFactory<AuditLogContext>, IDbContextFactory<LockContext>
This snippet will create migrations for the CoreContext
public class Program : IDbContextFactory<AuditLogContext>, IDbContextFactory<CoreContext>,IDbContextFactory<LockContext>
and the snippet will create migrations for the AuditLogContext.
It's a bit annoying but if you know how to create the migrations it's ok.

How to avoid references to Entity framework in multiple projects

I want to encapsulate Entity Framework in one project. This project will do DB access alone. When updating, I want to map a domain model to EF. The purpose is that other layers of the solution should have no knowledge of infrastructure.
My problem is that I need to reference EF in my "caller" project to make it work.
Is there a way to avoid this?
Solution
- ConsoleProject
- EntityFrameworkProject (EF from Nuget)
With EF6 and code based configurations, this is now possible.
[DbConfigurationType(typeof(MyDbContextConfiguration))]
internal class MyDbContext : DbContext
{
public DbSet<MyModel> MyModels { get; set; }
}
internal class MyDbContextConfiguration : DbConfiguration
{
public MyDbContextConfiguration()
{
SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance);
}
}
If you configure your database in Project A as above, then only Project A needs to reference EntityFramework, and any project that references it, like Project B will not try to find the provider in its own assembly.
Expose your repositories in Project A, and add a <connectionStrings> configuration in Project B, and it should work flawlessly.
I used this approach: https://stackoverflow.com/a/22970805/3874212
I reference the EntityFramework.SqlServer.dll only in the Console startup project.
I install entity Framework in my other project.
I create my model from DB in EF project
I move the connection string from the app.config in EF project to the Console project.
Unfortunately it is not possible for some strange reason. You must include EF package in client application too, not only in data access library.
It is possible to include only that DLL redlaz mentioned, but by doing this you are cooking lot of potential problems with versions.
Just overcome all reluctance and add EF package to your client application too.

Categories

Resources