I have the following problem with the .NET Core and Entity Framework.
I created myself the .NET Core project, I added DbContext and all the rest. My problem is that I can download the data without the slightest problem, unfortunately I can not save them, i.e. I have the Add method, but I do not have the SaveChanges method.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using CRM.Model.Entities;
namespace CRM.Model.Concrete
{
public abstract class ApplicationContext : IdentityDbContext<ApplicationUser>
{
public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options)
{
}
public DbSet<Category> Categories { get; set; }
public DbSet<Subcategory> Subcategories { get; set; }
public DbSet<SubcategoryL2> SubcategoriesL2 { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<ApplicationUser> Users { get; set; }
public DbSet<Coupon> Coupons { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<SubcategoryL2>().ToTable("Subs");
#region "Seed Data"
builder.Entity<IdentityRole>().HasData(
new { Id = "1", Name = "Admin", NormalizedName = "ADMIN" },
new { Id = "2", Name = "User", NormalizedName = "USER" }
);
#endregion
}
}
}
ICouponRepository
using System.Threading.Tasks;
using CRM.Model.Concrete;
namespace CRM.Repository.Abstract
{
public interface ICouponRepository
{
Task AddCoupon(Coupon coupon);
}
}
CouponRepository
using System.Threading.Tasks;
using CRM.Model.Concrete;
using CRM.Repository.Abstract;
namespace CRM.Repository.Concrete
{
public class CouponRepository : ICouponRepository
{
private readonly ApplicationContext _applicationContext;
public CouponRepository(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
}
public async Task AddCoupon(Coupon coupon)
{
await _applicationContext.Coupons.AddAsync(coupon);
await _applicationContext.SaveChangesAsync();
}
}
}
And the problem is here in CouponRepository, i.e.
I have no idea how I can fix it and why it does not work :(
CS1061 The "ApplicationContext" element does not contain the
definition of "SaveChangesAsync" and the available "SaveChangesAsync"
extension method was not found, which takes the first argument of the
"ApplicationContext" type (does not the using directive or the kit
reference?).
Second error
CS0012 C # The "IdentityDbContext <>" type is defined in an
unreferenced set. You must add a reference to the set
"Microsoft.AspNetCore.Identity.EntityFrameworkCore, Version = 2.2.0.0,
Culture = neutral, PublicKeyToken = adb9793829ddae60"
My project is divided into several smaller ones, that is, the main CRM project. In it there are several smaller ones:
CRM.Core
CRM.Services
CRM.Repository
CRM.Resources
CRM.Model
The problem is that without the slightest problem I use the ApplicationContext to retrieve data from the database, unfortunately I can not save any data with it, because the error pops up like in the picture.
when i change
public abstract class ApplicationContext :
IdentityDbContext
to
public abstract class ApplicationContext : DbContext
then all is Ok, but then Identity will not work for me
Solution:
The solution to my problem was to install the Microsoft.AspNetCore.Identity.EntityFrameworkCore package through the NuGet Package.
First of all you need to be calling SaveChangesAsync against the context, not the DbSet, so you should be writing this:
await _applicationContext.SaveChangesAsync();
Secondly, as a bonus, you shouldn't be using AddAsync unless you really need to, you should be doing this:
_applicationContext.Coupons.Add(coupon);
The docs state:
This method is async only to allow special value generators, such as the one used by 'Microsoft.EntityFrameworkCore.Metadata.SqlServerValueGenerationStrategy.SequenceHiLo', to access the database asynchronously. For all other cases the non async method should be used.
From the second error message it is clear what you have to do. Install Microsoft.AspNetCore.Identity.EntityFrameworkCore nuget package to the project where CouponRepository is located as follows:
PM> Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore -Version 2.2.0
Or you can also add Microsoft.AspNetCore.App meta-package to your CouponRepository project by adding the following item.
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
The error should go away now!
Related
I have been following this book on how to Add Identity to an existing project (specifically section 14.4). I have done the following
Added the ASP.NET Core Identity NuGet packages
Configured Startup to use Authentication Middleware and added Identity services to the DI container
Updated the EF Core data model with the Identity entities
Code for updating the EF Core data model to support Identity
namespace Hoook.Data
{
public class HoookDbContext : IdentityDbContext<ApplicationUser>
{
public HoookDbContext(DbContextOptions<HoookDbContext> options) : base(options)
{
}
public DbSet<Venture> Ventures { get; set; }
}
}
Code for custom user type which inherits from IdentityUser
namespace Hoook.Data
{
public class ApplicationUser : IdentityUser
{
}
}
Startup.cs code for adding Identity service to DI
services.AddDefaultIdentity<ApplicationUser>(options =>
options.SignIn.RequireConfirmedAccount = true).AddEntityFrameworkStores<HoookDbContext>();
Now I have then ran the following command in VSCode
dotnet ef migrations add AddIdentitySchema
Then I ran dotnet ef database update
At this point I am to assume my database is updated and contains the Identity tables, but that is incorrect. How Am I to add the Identity tables to my existing database? I have searched through these 1, 2, 3 stackoverflow questions with no luck.
Adding a screenshot of my SSMS Migration History and tables. The migration took but no Identity tables have been populated.
UPDATE
It may help to note, I have created an Identity app using the .NET Core CLI with new webapp -au Indi- vidual -uld. Inside the migrations of that app after running dotnet ef database update, the Migrations up and down methods are actually populated. However in my app when adding the migration following the above steps, my Migration file looks as so:
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Hoook.Migrations
{
public partial class AddIdentitySchema : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}
Thanks to the comments below and #DawoodAwan, I have figured out the missing piece. I did not override the OnModelCreating method and subsequently call the base.OnModelCreating() method inside of it. The solution is in the below code. I have also gone ahead and updated the names of the default tables in this example:
using Hoook.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace Hoook.Data
{
public class HoookDbContext : IdentityDbContext<ApplicationUser>
{
public HoookDbContext(DbContextOptions<HoookDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>().ToTable("Users");
builder.Entity<IdentityRole>().ToTable("Roles");
builder.Entity<IdentityUserClaim<string>>().ToTable("Claims");
builder.Entity<IdentityUserToken<string>>().ToTable("Tokens");
builder.Entity<IdentityUserLogin<string>>().ToTable("Logins");
builder.Entity<IdentityRoleClaim<string>>().ToTable("RoleClaims");
builder.Entity<IdentityUserRole<string>>().ToTable("UserRoles");
}
public DbSet<Venture> Ventures { get; set; }
}
}
I have an application with 3 layers (Presentation - Business - Data) built with Asp.Net MVC Core 2.1
In my Presentation layer I have an ApplicationDbContext class which instantiates and fills a test database:
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
SeedData(builder);
}
// Database Tables
public DbSet<Customer> Customers { get; set; }
public DbSet<Ingredient> Ingredients { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
public DbSet<Pizza> Pizzas { get; set; }
public DbSet<PizzaIngredient> PizzaIngredients { get; set; }
// Fill Database with sample data
private void SeedData(ModelBuilder builder)
{
// Seed data
}
Said class is injected within the Startup.cs class (also in presentation layer):
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>().AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest);
I now want to use this ApplicationDbContext class in the datalayer to keep code seperated. How would I best go about this? Injecting the class via constructor does not seem to work (Severity Code Description Project File Line Suppression State
Error CS0246 The type or namespace name 'ApplicationDbContext' could not be found (are you missing a using directive or an assembly reference?))
namespace PizzaShop.Data.Repositories
{
public class PizzaRepo : IPizzaRepo
{
private readonly ApplicationDbContext _context;
public PizzaRepo(ApplicationDbContext context)
{
_context = context;
}
public async Task<int> AddEntityAsync(Pizza entity)
{
_context.Pizzas.Add(entity);
return await _context.SaveChangesAsync();
}
//...
}
}
Architecture:
If you want to keep all database-related stuff in the PizzaShop.Data project, then your ApplicationDbContext doesn't belong in your web project. It belongs in your PizzaShop.Data project.
You then reference your PizzaShop.Data project from the web project.
Your ApplicationDbContext needs to be in the DataLayer.
References come from bottom to top which means from Presentation Layer References Business Layer References Data Layer. If you try to reference Presentation Layer in the Data Layer, cross reference problems occur. (it doesn't even makes sense).
As a result, move your ApplicationDbContext to where it belongs, which is the Data Layer and everything will be sorted out :)
I'm trying to get an existing postgresql database to work with Entity Framework Core 2. I've incorporated Microsoft.EntityFrameworkCore.Tools and Microsoft.EntityFrameworkCore.Design into my project. I've also set up the following in these files:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddEntityFrameworkNpgsql().AddDbContext<ApplicationDbContext > (options =>
options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
}
appsettings.json
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;User Id=postgres;Password=1234;Database=DEFAULTDATABASE;"
}
ApplicationDbContext.cs
using Microsoft.EntityFrameworkCore;
namespace SLCore.Models
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options): base(options)
{
}
public DbSet<TodoItem> TodoItems { get; set; }
}
}
TodoItem.cs
namespace SLCore.Models
{
public class TodoItem
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
}
At this point it's my understanding I should migrate the database using
dotnet ef migrations add InitialMigration
But I am not seeing how to open the dotnet CLI in VS 2017 Community, and I have tried it in powershell and it threw the following error:
No executable found matching command "dotnet-ef"
I also tried
Scaffold-DBContext "Server=localhost;User Id=postgres;Password=1234;Database=DEFAULTDATABASE;" Npgsql.EntityFrameworkCore.PostgreSQL -o Models
and I got the following error:
Scaffold-DBContext : The term 'Scaffold-DBContext' is not recognized as the name of a cmdlet, function, script file,
or operable program.
After a lot of searching it seems like this should be the next step, but I'm stumped. Any suggestions?
I created a WCF / EF code first service. I created a folder called "Models" and there created my /POCOs. In there I created my context. Now in the Package Manager Console I run enable-migrations. This returns Success and adds the Migrations folder and /Configuration.cs. Now the problem shows itself.
The auto-generated code in Configuration.cs looks like this;
internal sealed class Configuration :
DbMigrationsConfiguration<MyService.**Models**.MyContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
}
protected override void Seed(MyService.**Models**.MyContext context)
Now under the word Models I get the red squiggle and the error message
The type name Models does not exist in the type MyService.MyService.
I have tried everything including renaming the Namespace and the folder. Anywhere the myContext file is placed will cause this error.
I've tried deleting all existence of the Entity Framework and starting over many times but still can't figure this one out! :/
namespace MyService.Models>
{
public class MyContext : DbContext
{
public DbSet<Chain> Chains { get; set; }
public DbSet<Shop> Shops { get; set; }
}
}
Code
using System.Web;
abstract class CookieHandler
{
public CookieHandler(string domain)
{
CookieDomain = domain;
}
public string CookieDomain { get; set; }
public abstract void SetCookie(HttpContextBase context, CookieHandler value);
}
HttpContextBase gives me the error "type or namespace HttpContextBase cannot be found" Same error when i try HttpContext. I am trying to figure out why I cannot take in this object anymore.
I am using .NET Framework 4.5.2 and have it has a Library class project.
Per recommendation from user comment, the issue was I had to reference the assembly system.web.dll