How can I create the database entities in a layered application - c#

I have to create a layered .net core application including a database. I want to build the database entities with sql-first approach. The solution looks like this:
All of the projects are class libaries, except the FoodSupplementCompany.Program.
My question is, how can I use Scaffold-DbContext to generate the entities to the FoodSupplementCompany.Data project?

You can use the Package Manager Console:
cd .\FoodSupplementCompany.Data
dotnet ef dbcontext scaffold -s ..\FoodSupplementCompany.Program
The line cd .\FoodSupplementCompany.Data is for navigating into project directory where the DBContext is located.
And the line -s ..\FoodSupplementCompany.Program is for stating where is the startup project to use.

As the guide here states: scaffold-dbcontext
Example:
Scaffold-DbContext
"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;"
Microsoft.EntityFrameworkCore.SqlServer
-OutputDir Models
-OutputDir -> The directory to put files in. Paths are relative to the project directory.

Related

Scaffolding an existing SQLite database with EF core results in a generic context and no entities for the tables

The command I'm inputting into pmc is
Scaffold-DbContext "DataSource=C:\SQLite\Databases\Ticket0.db3" Microsoft.EntityFrameworkCore.Sqlite -OutputDir C:\WPFTutorials\TicketEF\TicketEF\DB -context TicketContext -force
I've checked and double checked the data source, but it only generates a generic context and no tables (I can't include images as I don't have high enough reputation).
I also checked on stack overflow but the closest relevant post I could find was this SQLite scaffolding with Entity Framework Core, however the problem there was relative pathing whereas I am using an absolute path.
Another I tried was Scaffold (reverse engineering) existing database return empty sets and tried commenting out the <Nullable>enable</Nullable> which solved their issue but that didn't work either.
I have the
Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Design, Microsoft.EntityFrameworkCore.Sqlite and Microsoft.EntityFrameworkCore.Tools
NuGet packages installed.
In case it matters the database I am trying to connect can be opened and changed in SQLiteStudio so it should be working fine, and it has 5 tables and 2 views.
I have modified your code to the below and it's working.
Scaffold-DbContext -provider Microsoft.EntityFrameworkCore.Sqlite "DataSource=C:\SQLite\Databases\Ticket0.db3" -OutputDir C:\WPFTutorials\TicketEF\TicketEF\DB -context TicketContext -force
What had happened was that I mistyped the database location as "Ticket0" which is how it appeared in SQLiteStudio and EF Core generated an empty Ticket0.db3 which I'd then mistaken for the original file.
Since it's my own mistake should I delete the question?

dotnet ef dbcontext scaffold does not run correctly from code

I am trying to create a model from an existing database from c# code.
The statements I use are exactly the ones given in the Microsoft documentation at https://learn.microsoft.com/en-us/ef/core/get-started/overview/first-app?tabs=netcore-cli
and I am simply executing them via a process created in c# code.
When executed directly from the command line the entity model is generated correctly for both the db context and the classes for the entities.
When executed via a process from VS2022 the statements run correctly without reporting an error but only the db context is generated, and no classes for the entities are created.
If you run in an empty folder the statements as generated by the code, ie:
dotnet new console
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet ef dbcontext scaffold "Server=***.***.***.***;User Id=******;Password=*********" Microsoft.EntityFrameworkCore.SqlServer -o Model -f -v
and examini the result folder, in the Model folder you will find the dbcontext AND all the entities definitions for the database.
I am confused at this point, and would like to hear from anybody who might have an idea of what is happening.

How to create migrations from library project by targeting a Web Api project and use the lib project as the migrations assembly?

I created a .Net 5 Web Api project and a library project. In the library project I created a database entity, a context and an extension to register the context on startup
public static IServiceCollection AddContexts(this IServiceCollection services)
=> services.AddDbContext<CarsContext>(x => x.UseNpgsql("Host=host;Database=db;Username=user;Password=pw"));
In the Web Api project I call the AddContexts method in the startup file. With the EF cli I want to generate migrations in the lib project by calling this in the Api directory
dotnet ef migrations add Init --startup-project . -o ./LibProj
The build succeeds but unfortunately I get this error
Your target project 'ApiProj' doesn't match your migrations assembly
'LibProj'. Either change your target project or change your migrations
assembly. Change your migrations assembly by using
DbContextOptionsBuilder. E.g. options.UseSqlServer(connection, b =>
b.MigrationsAssembly("ApiProj")). By default, the migrations assembly
is the assembly containing the DbContext. Change your target project
to the migrations project by using the Package Manager Console's
Default project drop-down list, or by executing "dotnet ef" from the
directory containing the migrations project.
I don't think my Api project should deal with database related things. Is there a way I can fix my command to use the Api project as the startup project but take the context from the lib project and put the migrations into the lib project?
Use the --project flag for the dotnet ef command as well:
dotnet ef migrations add Init --startup-project ./ApiProj --project ./LibProj -o ./LibProj
The --project flag sets the target project. Change the paths for each flag as needed, but I think that should give you what you need.
To run this commands from your library project you can Add packages to your library project:
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.SqlServer
After that you can ran ef commands from your library folder and reference it to your ApiProj.
Example:
dotnet ef --startup-project ../ApiProj migrations add init
dotnet ef --startup-project ../ApiProj database update

Unable to retrieve project metadata. Ensure it's an MSBuild-based .NET Core project. (Migrations)

I have a project with this structure
TooSeeWeb.Infrastructure is for migrations.
When I try to run migrations with this command
dotnet ef migrations add ExampleMigration -s ..\TooSeeWeb
I have this error
Unable to retrieve project metadata. Ensure it's an MSBuild-based .NET Core project. If you're using custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, Use the --msbuildprojectextensionspath option
How I can fix this?
This is 2 years old but I was just in the same situation so it is still relevant. It's first result on Google for this error.
So I can see in your Screenshot that you are not in the standard Windows Visual Studio so I assume you are not on Windows (makes a difference in how to write file paths). Also I can see that you used ..\TooSeeWeb with a backslash.
Solution: Change all \ to a / forward slash so in your case I guess it would be:
dotnet ef migrations add ExampleMigration -s ../TooSeeWeb
For me it was working on Windows but failing on macOS (OS X) with this error:
Unable to retrieve project metadata. Ensure it's an SDK-style project.
If you're using a custom BaseIntermediateOutputPath or
MSBuildProjectExtensionsPath values, Use the
--msbuildprojectextensionspath option.
Additionally it gives the information (that gives a better hint):
MSBUILD : error MSB1009: Project file does not exist.
Here my more complex statement WORKING with forward slashes:
dotnet ef --startup-project ./MainProject.csproj migrations add MyMigration --context MyDbContextPostgreSQL --output-dir Migrations --project ../MyDatabasePostgreSQL/MyDatabasePostgreSQL.csproj
You have to point to your web project
dotnet ef --startup-project ../TooSeeWeb migrations add MigrationName -c NameOfYourDBContext
More details about multi project you can find https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/projects
I had the same error. I solved it by including the nuget package:
Microsoft.EntityFrameworkCore.Tools
just add the path to your startup project and database project like this:
dotnet ef database update --verbose --project "src/Services/Discount/Discount.Infrastructure.Rdms" --startup-project "src/Services/Discount/Discount.Web"
The path should be relative to your current directory to the destination directory, for instance, if I change my current directory to /src the path would be Services/Discount/Discount.Infrastructure.Rdms
The problem for me was that the project was in the solution folder so I had to specify the project path like this
dotnet ef migrations add InitialCreate --project SolutionName/ProjectName.csproj
My error was similar, but different. In fact the same error as #CodingYourLife mentions (perhaps the error wording has changed over time, or it is in fact a different error), anyway... This was the error:
Unable to retrieve project metadata. Ensure it's an SDK-style project. If you're using a custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, Use the --msbuildprojectextensionspath option.
It turned out that I needed to run the dotnet ef dbcontext scaffold <list_of_options> command from the parent folder (the one with the solution file in it - not from the PROJECT folder). I used cd .. (to move up one folder) and re-ran the command, and it created my database-context and EF classes for the tables specified.
I don't know how this problems appeared.
But i truly know that most developers come from using these commands:
dotnet ef migrations add "MigrationName" -s ../ProjectName
dotnet ef migrations remove -s ../ProjectName
dotnet ef database update -s ../ProjectName
So replaced them with these:
dotnet ef --startup-project ../ProjectName migrations add
MigrationName -c DbContextName
dotnet ef --startup-project ../ProjectName database update -c
FoodTownDbContext
I think the same apply for this,but haven't tested it:
dotnet ef --startup-project ../ProjectName migrations remove
-c DbContextName
first of all, your need to see the exact context name. This is needed for
dotnet ef migrations add -c <your context name>
You can see your contexts in your project by using this command:
dotnet ef dbcontext list
You will see something like below👇
AspNetCore.Jwt.Sample.Config.MyIntIdentityContext
AspNetCore.Jwt.Sample.Config.MyIdentityContext
See... there is more than one context. Choose&copy your context's full name and paste it after -c option
dotnet ef migrations add Initial -c AspNetCore.Jwt.Sample.Config.MyIntIdentityContext
use as above☝.
and that is ok! It works well now.
possible reasons:
main reason is your project includes more than one context class
in my case. Context class was in a file with other classes.(i.e.) this config (.cs)file from this impressive github repository
usually I have this problem when I receive updates for dotnet sdks. ProgramFiles/dotnet/sdk.
The problem is that I use an MSBuildSDKsPath system variable and this path doesn't update after dotnet sdk updates.
If you face the same problem, and use the same system variable, that can be the solution.
I am using Entity Framework Core .NET Command-line Tools 6.0.10, and the following worked for me.
Make sure you install the EF tooling globally
dotnet tool install dotnet-ef --global
Make sure you update it to the latest
dotnet tool update dotnet-ef --global
Open a Powershell off your start up project. In your case, it would be TooSeeWeb? Your Powershell should default the root to something like
PS C:\your-user\source\repos\TooSeeWeb\src\TooSeeWeb>
Run the following command to add a migration
dotnet ef migrations add ExampleMigration
-c YourDbContext
-p ../TooSeeWeb.Infrastructure
-o Data/Migrations
-p should set the project where you want the migrations to be put in.
-o is the directory you want to put files in, and it's relative to the project directory you just set with -p.
You can also use -s to set the start up project, where you have your connection string. But since I open the Powershell off the start up, I don't have to specify this, as it defaults to the current working directory.
You can do dotnet ef migrations add -h to see the whole list of optional arguments and what they do.
In my case it was caused by EF versions that I had installed.
I had Entity Framework Core .NET Command-line Tools 7.0.1 installed and the project I was trying to add the migration to, was using EF 6.
Solution was to run EntityFramework6\Add-Migration instead of Add-Migration

How to scaffold DbContext with plural DbSet property names in Entity Framework Core?

I use Scaffold-DbContext command in Package Manager Console to create and re-create context and entities for an existed SQL Server database:
Scaffold-DbContext -provider EntityFramework.MicrosoftSqlServer -connection "my connection string"
It works perfectly except one thing: DbSet's have property names in singular form:
public partial class MyDbContext : DbContext
{
public virtual DbSet<Request> Request { get; set; }
public virtual DbSet<RequestHeader> RequestHeader { get; set; }
}
I prefer these names to be in plural form (Requests etc.). In addition to web search I checked command syntax:
get-Help Scaffold-DbContext -detailed
And found nothing to change this behaviour. Here is my packages.config:
<packages>
<package id="EntityFramework.Commands" version="7.0.0-rc1-final" targetFramework="net46" />
<package id="EntityFramework.Core" version="7.0.0-rc1-final" targetFramework="net46" />
...
</packages>
How to pluralize DbSet names when scaffolding?
UPDATE 2017-04: DB First scaffolding pluralization is now possible in Entity Framework Core 1.1. Read my answer below for details.
Short Answer
1. Install Package
Install-Package Bricelam.EntityFrameworkCore.Pluralizer
2. Run Scaffold-DbContext Command
Scaffold-DbContext -Connection "Server=<server>;Database=<dbname>;user id=<userid>;password=<pwd>;" -Provider Microsoft.EntityFrameworkCore.SqlServer -OutputDir Data/EFModels/
Long Answer:
As pointed out by #KalinKrastev in the comments of #natemcmaster's answer. Pluralization in EF Core is possible using a package called Bricelam.EntityFrameworkCore.Pluralizer that can be installed using
in the Package Manager Console (PMC) or
dotnet add package Bricelam.EntityFrameworkCore.Pluralizer
using Dotnet cli.
After installing the package just use the regular Scaffold-DbContext command.
Scaffold-DbContext -Connection "Server=<server>;Database=<dbname>;user id=<userid>;password=<pwd>;" -Provider Microsoft.EntityFrameworkCore.SqlServer -OutputDir Data/EFModels/ -Force
See More About Bricelam's Pluralizer
You can use this command :
Scaffold-DbContext "connectionString" Microsoft.EntityFrameworkCore.SqlServer -o Models -UseDatabaseNames -NoPluralize -force
You have nuget package before:
Microsoft.EntityFrameworkCore.Design - version 5
Microsoft.EntityFrameworkCore - version 5
Microsoft.EntityFrameworkCore.SqlServer -version 5
Microsoft.EntityFrameworkCore.Tools - version 5
Microsoft.EntityFrameworkCore.Relational -version 5
Update for EntityFrameworkCore 5.0 : TableNames are now automatically pluralized upon scaffolding. (At least with -Provider Microsoft.EntityFrameworkCore.SqlServer)
Pluralization is possible in EF Core 1.1. As Rowan Miller described in its blog, you need to install the Inflector and implement IDesignTimeServices to control pluralization when scaffolding. However, be aware of it:
We put these services into *.internal namespaces and reserve the right
to break the APIs at any point.
So this is why a full code example is not copied to here. This answer is not accepted for the same reason - I prefer to wait until we get a stable API.
Another issue you should consider - this solution is provider-dependent. It works fine with SQL Server (I tested it). Another DBMS provider may not support this API yet. For example, latest Npgsql.EntityFrameworkCore.PostgreSQL 1.1.0 fails on scaffold when custom IDesignTimeServices is used.
Pluralization is not supported in EF7 as of RC1. This and other limitations of EF7 scaffolding are being tracked here: https://github.com/aspnet/EntityFramework/issues/4038
I may be late to the party, but after an upgrade from .net core 3.1 to .net 6, when I used the following command: dbcontext scaffold "Server=(local);Database=XXXXXX;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o Models\Entities -c DBContext -f --verbose --no-onconfiguring --startup-project ../XXXX^ it duplicated my entities by generating the singluar form of them. Up until the upgrade de command was giving me the name from the database of the entities so it was not adding the duplicated singular form. I found that using the --no-pluralize option kept the command from generating another entity with singular form. I know they added a default pluralizer in net core 5, but I have no ideea why this worked in preventing the singularization. So Cris Loli's aswer seems to solve my issue. Hope this helps someone solve their issues.

Categories