How to avoid references to Entity framework in multiple projects - c#

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.

Related

Circular dependency when generating dbcontext migrations into another assembly

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...

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.

Cannot add migration with ASP.net Core 2

I'm building a new project using ASP.net Core 2 and EntityFrameWorkCore 2.1.0 and I began to build the database structure. Now I have to make my first Migration to get my database ready and when I execute 'Add-Migration Init' into the Package Manager Console I got this error:
The current CSharpHelper cannot scaffold literals of type 'Microsoft.EntityFrameworkCore.Metadata.Internal.DirectConstructorBinding'. Configure your services to use one that can.
Also I tried this documentation https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/migrations and the message I got is:
Unable to create an object of type 'ApplicationDbContext'. Add an implementation of 'IDesignTimeDbContextFactory<ApplicationDbContext>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
I also followed this article without any success.
If I try without Microsoft.AspNetCore.Identity.EntityFrameworkCore 2.0.2 and with a simple 2 tables structure I'm able to make it work.
So now I need your help...
Make sure that you have the required NuGet packages installed:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Design
I found some reasons why we can get hard time to use migration with the latest version of ASP.net Core 2 at this time.
First of all, if you just migrate from an old project which is not built from ASP.net Core at all, you will have to add a Context Factory to make Migrations work. Here my own Context Factory:
public class ApplicationDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
{
public ApplicationDbContext CreateDbContext(string[] args)
{
var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
builder.UseSqlServer("Server=(local)\\SQLEXPRESS;Database=yourdatabase;User ID=user;Password=password;TrustServerCertificate=True;Trusted_Connection=False;Connection Timeout=30;Integrated Security=False;Persist Security Info=False;Encrypt=True;MultipleActiveResultSets=True;",
optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(ApplicationDbContext).GetTypeInfo().Assembly.GetName().Name));
return new ApplicationDbContext(builder.Options);
}
}
If you divided your project into layers for architecture purpose, add the Context Factory inside the Repository Layer or in the same library where your DbContext is.
Secondly, before any attempt to add a migration, you must set the selection of “set as startup project” on the repository library or where your DbContext is.
Then, those are the packages you need to use for migration:
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
That’s all!
Be careful when you add other packages because they can break the Migration system. As an example, if you use a Unit of Work & Repositories Framework like URF and install URF.Core.EF.Trackable -Version 1.0.0-rc2, you will no longer be able to add migration. Instead use URF.Core.EF.Trackable -Version 1.0.0-rc1. I guess this can happen with many other packages as well.
Finally, read this article will be helpful. It’s a little outdate but it can help people out there.
Cheers
How do you arrange the main method in "Program.cs"?
This error can be amenable to a old initialization pattern.
From the Asp Net migrations guidelines:
The adoption of this new 2.0 pattern is highly recommended and is
required for product features like Entity Framework (EF) Core
Migrations to work. For example, running Update-Database from the
Package Manager Console window or dotnet ef database update from the
command line (on projects converted to ASP.NET Core 2.0) generates the
following error:
Unable to create an object of type ''. Add an implementation of 'IDesignTimeDbContextFactory' to the
project, or see https://go.microsoft.com/fwlink/?linkid=851728 for
additional patterns supported at design time.
Check at this link of the correct implementation
In my case, the dbcontext was different in Startup within ApplicationDbContext class.
services.AddDbContext<DbContext>
to
services.AddDbContext<ApplicationDbContext>

Enable Migrations from context on different assembly

So basically I've two projects on the same solution. One of the projects its a class library where I have the all the Models and the Database Context class. The other one is a Web API. I want to use Nuget to Enable-Migrations on the Web API project but I always get the "No context type was found in the assembly Pr.WebApi.
So far I've tried:
Enable-Migrations -ContextTypeName Pr.ClassLibrary.Models
Any Ssuggestions?
When theres no data to store in a database in your WebAPI-Project, you dont need Entity Framework at all in this project. If you store data over your Class library, you can use the context from the class library project.
You will use Enable-Migrations in the Package Manager Console. Make sure that the default project on the top of the package manager console is set to your class library. That is the only project you need to enable the migrations on.
Enable-Migrations should be invoked in your class library...

Entity Framework cannot access entity classes

I have used Entity Framework for DAL in a few projects but in the one I'm working on right now, I have the edmx file in a class library project and that's all there is in the project. I have this project referenced in another class library project and for some reason I'm not able to access any of the entity classes that are defined in the .designer.cs file. I can't access the context class either. If i look at the referenced project in Object viewer in visual studio, it does not list any entities for this project.
Does anyone know why I'm not able to access the entity classes or the datacontext in another project?
EDIT: If it makes any difference, it's associated with a database on sql azure.
This is can happen into two different ways. One is to make sure the Entity Model class are public. The other is to check the Entity Model Namespace is matches to the Context class.
I was able to resolve it by deleting the existing edmx file and regenerating a new one.
Apparently the old one got into a weird state, I was not able to figure out how to get it to work again.
I have used Entity Framework for DAL in a few projects but in the one I'm working on right now, I have the edmx file in a class library project and that's all there is in the project. I have this project referenced in another class library project where i was not able to initialize the object for the entity class saying connection string was not set ,where i have checke with the connection string which was there.\
check your inherited class of DbContext, it must be public
Check the Namespaces of the Context class and Designer.cs class.

Categories

Resources