ASP.NET EF with class library - entity-framework

I created a class library which is going to have my database model with DB first approach. I am using the Northwind database.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<NorthwindContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("NorthwindContext"));
});
}
In this method in asp.net project it tells me that the NorthwindContext is not convertible to DBcontext but the class inherits from it:
Error CS0311
The type 'NorthwindDal.NorthwindContext' cannot be used as type parameter 'TContext' in the generic type or method 'EntityFrameworkServiceCollectionExtensions.AddDbContext(IServiceCollection, Action?, ServiceLifetime, ServiceLifetime)'.
There is no implicit reference conversion from 'NorthwindDal.NorthwindContext' to 'Microsoft.EntityFrameworkCore.DbContext'.
If I don't use the AddDbcontext and try to run the project, it just tells me that it cannot find the connection string for the database.
The context is auto created and it inherits from the DBcontext as well.
I think its probably because I try to use the class library to do this but is there a way to use class library with ASP.NET?
Northwind Context
public partial class NorthwindContext : DbContext
{
public NorthwindContext()
: base("name=NorthwindContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<CustomerDemographic> CustomerDemographics { get; set; }
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<Employee> Employees { get; set; }
public virtual DbSet<Order_Detail> Order_Details { get; set; }
public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<Product> Products { get; set; }
public virtual DbSet<Region> Regions { get; set; }
public virtual DbSet<Shipper> Shippers { get; set; }
public virtual DbSet<Supplier> Suppliers { get; set; }
public virtual DbSet<Territory> Territories { get; set; }
}

Based on your scenario if you would like to implement "database first approach" you could follow the below steps.
Database Schema:
You can download Northwind database schema from our official site as well. Just for reference.
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
Note: You can set any meaningful connection string name here in DefaultConnection as I have set this.
DbContext class:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<Categories> Categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Categories>().ToTable("Categories");
}
}
appsettings.json:
"ConnectionStrings": {
"DefaultConnection": "Server=YourServerName;Database=Northwind;Trusted_Connection=True;MultipleActiveResultSets=true"
}
Controller:
public class NorthwindController : Controller
{
private readonly MvcAttendanceDbContext _context;
private IHostingEnvironment _hostEnvironment;
public NorthwindController(IHostingEnvironment _environment, MvcAttendanceDbContext context)
{
_hostEnvironment = _environment;
_context = context;
}
public IActionResult Index()
{
var categories = _context.Categories.ToList();
return View(categories);
}
}
View:
#model IEnumerable<MVCApps.Models.Categories>
<h3 class="card-title"><strong>Northwind Category</strong> </h3>
<div class="row">
#foreach (var item in Model)
{
<div class="col-sm-4">
<div class="card" style="width: 18rem;border:1px;padding: 2px 2px 2px 2px; margin-bottom:20px;box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;">
<div class="card-body">
<h5 class="card-title"><strong>#Html.DisplayFor(modelItem => item.CategoryName)</strong> </h5>
<p class="card-text">#Html.DisplayFor(modelItem => item.Description)</p>
<a asp-action="Details" class="btn btn-primary" asp-route-memberId="#item.Description">Details</a> | <a asp-action="EditMember" class="btn btn-warning" asp-route-memberId="#item.CategoryID">Edit</a>
</div>
</div>
</div>
}
</div>
Output:

To generate model classes and database context from an existing database you need to use ef tool scaffolding. You can do it using the command
dotnet ef dbcontext scaffold "Your connection string" Microsoft.EntityFrameworkCore.SqlServer
You need the add reference following NuGet packages if you need to run the command.
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

Related

DropDownList from Existing DataBase [Asp.Net Core 2.0 MVC Enity Framework]

I hope you can help me I want to bind the DropDownList
and get the data from an existing Database. Visual Studio doesn't show error but when i Run the app it tells me to migrate my DB even though I've already migrated it.
here's my code.
Create.cs
<div class="form-group">
<label asp-for="DomWasAccNo" class="control-label"></label>
<select asp-for="DomWasAccNo"
class="form-control"
asp-items="#(new SelectList(#ViewBag.ListOfConsumer, "AccountNo","AccountNo"))"></select>
<span asp-validation-for="DomWasAccNo" class="text-danger"></span>
</div>
LibCustomers.cs
This part is autogenerated using this CLI command "dotnet ef dbcontext scaffold "Server=192.168.1.28;Database=SBMA_TUBS;User Id=sa;" Microsoft.EntityFrameworkCore.SqlServer -d -o Model -c "CustomerDbContext"
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace WWFS.Models
{
[Table("LIB_CONSUMERS")]
public partial class LibConsumers
{
[Column("account_no")]
[StringLength(15)]
public string AccountNo { get; set; }
[Column("consumer_name")]
[StringLength(255)]
public string ConsumerName { get; set; }
[Column("address")]
[StringLength(255)]
public string Address { get; set; }
}
}
Controller.cs
List<LibConsumers> libConsumers = new List<LibConsumers>();
libConsumers = (from cons in _context.LibConsumers
select cons).ToList();
libConsumers.Insert(0, new LibConsumers { AccountNo = "Select" });
ViewBag.ListOfConsumer = libConsumers;
DomesticWaste.cs
using Microsoft.EntityFrameworkCore;
namespace WWFS.Models
{
public class DomesticWasteDbContext : DbContext
{
public DomesticWasteDbContext(DbContextOptions<DomesticWasteDbContext> options)
: base(options)
{
}
public DbSet<WWFS.Models.DomesticWaste> DomesticWastes { get; set; }
public DbSet<WWFS.Models.Location> Locations { get; set;}
public DbSet<WWFS.Models.Contractor> Contractors { get; set; }
public DbSet<WWFS.Models.LibConsumers> LibConsumers { get; set; }
}
}
CustomerDbContext.cs
This part is autogenerated using this CLI command "dotnet ef dbcontext scaffold "Server=192.168.1.28;Database=SBMA_TUBS;User Id=sa;" Microsoft.EntityFrameworkCore.SqlServer -d -o Model -c "CustomerDbContext"
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace WWFS.Models
{
public partial class CustomerDbContext : DbContext
{
public virtual DbSet<LibConsumers> LibConsumers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(#"Server=192.168.1.28;Database=SBMA_TUBS;User Id=sa;");
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<LibConsumers>(entity =>
{
entity.Property(e => e.AccountNo).ValueGeneratedNever();
entity.Property(e => e.ConsumerName).ValueGeneratedNever();
entity.Property(e => e.Address).ValueGeneratedNever();
});
}
}
}
i think no one can answer this question.

Many-to-many relationship and multi select in asp.net core

I'm trying to learn asp.net core with razor and I'm trying to make a videogame database to keep a track of finished games, games I haven't played yet, etc.
But I have a problem. I have a table Game and a table Developer. Since a game can have many developers and a developer can have many games y made a third table DeveloperXGame.
They are something like this
public class Game
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Developer
{
public int Id { get; set; }
public string Name { get; set; }
}
public class DeveloperXGame
{
public int DeveloperId { get; set; }
public int JuegoId { get; set; }
public Developer Developer { get; set; }
public Game Game { get; set; }
}
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Game> Game { get; set; }
public DbSet<Developer> Developer { get; set; }
public DbSet<DeveloperXGame> DeveloperXGame { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<DeveloperXGame>()
.HasKey(m => new { m.DeveloperId, m.GameId });
}
}
I already did the pages for the developers so I first create them manually. Now I'm trying to create the games and I want to show a select where I can select one or more developers of that list (next step will be to try to add them with ajax through the games page if they don't exists). But I'm lost beyond this point.
I don't know how to load the list of developers in that list and later on post how to save those selected items in the table DeveloperXGame.
Thanks
You can remove public DbSet<DeveloperXGame> DeveloperXGame { get; set; } from your context.
Index.cshtml.cs
public class IndexModel : PageModel
{
private readonly ApplicationDbContext _context;
public IndexModel(ApplicationDbContext context)
{
_context = context;
}
public Game Game { get; set; }
public IEnumerable<int> Developers { get; set; }
public IEnumerable<SelectListItem> DeveloperList { get; set; }
public IActionResult OnGet()
{
var developers = from m in _context.Developers
select m;
DeveloperList = developers.Select(m => new SelectListItem { Value = m.Id.ToString(), Text = m.Name });
return Page();
}
}
Here is the view Index.cshtml
#page
#model RazorPages.TestGame.Pages.Games.IndexModel
#{
ViewData["Title"] = "Index";
}
<div class="row">
<div class="col-md-4">
<form method="post">
<div class="form-group">
<label asp-for="Game.Name" class="control-label"></label>
<input asp-for="Game.Name" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Developers" class="control-label"></label>
<select asp-for="Developers" asp-items="Model.DeveloperList">
<option value="">All</option>
</select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
You can also use ViewData to pass your developers list in your view. You can go through this sample web as in official doc here.Hope it helps you to get started!

Add TPT Inherited Code First Model to Linq Fluent API

I'm having problems extending the Fluent API to my inheritance classes. I have taken the TPT (table per type) method and each type of the inheritance has a table. I like table per type because the database is fully normalized and easy to maintain. I am not getting the inherited model ServiceCompany to work with the Fluent API.
Base Abstract Class
public abstract class Vendor
{
[Key]
public int VendorID { get; set; }
[Required]
public string CompanyName { get; set; }
[Required]
public int StreetNumber { get; set; }
[Required]
public string StreetName { get; set; }
}
Inherited ServiceCompany Class from Vendor
[Table("ServiceCompanies")]
public class ServiceCompany : Vendor
{
public string ACHClaim { get; set; }
public virtual ICollection<SubContractorCompany> SubContractorCompanies { get; set; }
public virtual ICollection<ServiceCompanyUser> SubContractorUsers { get; set; }
}
Where I added the entity models to enable the Fluent API with onModelCreating()
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<Vendor> Vendors { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ServiceCompany>().ToTable("ServiceCompanies");
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
I would like to be able to do something like this with the fluent API.
var ListofServiceCompanies = db.ServiceCompanies.All()
and not like this
var ListofServiceCompanies = db.Vendor.SelectMany( Vendor is a ServiceComapny...etc)
I prefer to set up the entities correctly and make the code nice and easy to use. Any insight or knowledge is appreciated.
You can do that by calling OfType extension method like below:
var ListofServiceCompanies = db.Vendor.OfType<Vendor>().ToList();
Or you can just add a DbSet<ServiceCompany> ServiceCompanies { get; set; } into your DbContext so it will look like this:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public DbSet<Vendor> Vendors { get; set; }
public DbSet<ServiceCompany> ServiceCompanies { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ServiceCompany>().ToTable("ServiceCompanies");
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
Then just call:
var ListofServiceCompanies = db.ServiceCompanies.ToList();

InvalidCastException in Entity Framework 7

I'm using Visual Studio 2015, .Net framework 4.6.00079 to build a simple ASP.NET MVC 6 app:
model:
namespace RimconPensionModel.DataAccessLayer
{
[Table("BaseMortality")]
public class BaseMortality
{
[Key]
public int Id { get; set; }
public string BaseMortalitySet { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public float MortalityFactor { get; set; }
public DateTime EffectiveDate { get; set; }
public DateTime UpdateDate { get; set; }
public string UpdateUser { get; set; }
}
}
controller:
namespace RimconPensionModel.Controllers
{
public class BaseMortalityController : Controller
{
[FromServices]
public RimconPensionModelContext RimconPensionModelContext { get; set; }
[FromServices]
public ILogger<BaseMortalityController> Logger { get; set; }
public IActionResult Index()
{
return View(RimconPensionModelContext.BaseMortality.ToList());
}
}
}
view:
#model IEnumerable<RimconPensionModel.DataAccessLayer.BaseMortality>
#{
ViewBag.Title = "Base Mortality Data";
}
<h2>Base Mortality Data</h2>
<!--
<p>
<a asp-controller="BaseMortalityData" asp-action="Create">Create New</a>
</p> -->
<table class="table">
<tr>
<th>Base Mortality Sets</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.BaseMortalitySet)
</td>
</tr>
}
</table>
The app builds and starts, but when I invoke the controller, I get InvalidCastException on the "return View( . . . )" line of the controller. I've been googling for days (I'm a bit new to MVC and Entity Framework) with no luck. I think it probably has something to do with the datetime attributes. I bulk loaded the database table from a csv file with the datetime fields in YYYYMMDD format and the load went OK; the db table shows 1994-12-31 12:00:00 AM in the datetime fields. They are type datetime2(7), NOT NULL in the db.

MVC4 Entity Framework 5 Many-To-Many Save Entity to Database

Hi I've been stuck to long on this problem. I've looked at a lot of examples but i cant find what im looking for. Any help is appreciated.
I use the Code-First approach.
I've enabled migration and the database is fine [Student] - [StudentCourse] - [Course].
Scenario: I have two entites -> Student
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Course> Courses { get; set; }
}
And Course
public class Course
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual List<Student> Students { get; set; }
}
Nothing fancy about that... Ive created a ViewModel ->
public class StudentCourseViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<Course> Courses { get; set; }
}
View:
#model Project.Web.Models.StudentCourseViewModel #{
ViewBag.Title = "Edit"; }
Edit
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Student</legend>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Courses)
</div>
<div class="editor-field">
#for (int i = 0; i < Model.Students.Count(); i++)
{
<div style="border: dotted 1px; padding: 5px; margin: 10px;">
#Html.HiddenFor(s => s.Students[i].Id)
#Html.LabelFor(s => s.Students[i].Name[i + 1])
#Html.EditorFor(s => s.Students[i].Name)
</div>
}
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset> }
Controller Action:
[HttpPost]
public ActionResult Edit(CourseStudentViewModel model)
{
var course = db.Courses.Find(model.CourseId);
course.Name = model.CourseName;
course.Description = model.CourseDescription;
course.Students = model.Students;
if (ModelState.IsValid)
{
db.Entry(course).State = System.Data.EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
(Maby this is were i go wrong...)
Anyway, I want to create a new Student with optional many courses (textboxes -> courseName)
How should i do this?
The main issue is that i always get null values (student is fine, List of courses = NULL) back from my view [httpPost]Create -action.
I'm in need of guidance how to make this approach possible.
Thx J!
Your entities are not setup correctly for a many-to-many relationship. You need another entity to handle the many-to-many mapping. It would look something like this.
public class StudentsToCourses
{
public int StudentId {get; set;}
public int CourseId {get; set;}
public virtual Student Student {get; set;}
public virtual Course Course {get; set;}
}
Then your student model should be changed to this.
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<StudentsToCourses> Courses { get; set; }
}
And your coursed model changed to this.
public class Course
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual List<StudentsToCourses> Students { get; set; }
}
You also need to setup the foreign key relationship using the Fluent API. It would look something like this.
public class StudentsToCoursesConfiguration : EntityTypeConfiguration<StudentsToCourses>
{
internal StudentsToCoursesConfiguration ()
{
this.HasKey(p => new {p.StudentId, p.CourseId});
this.HasRequired(p => p.Student)
.WithMany(p => p.Courses)
.HasForeignKey(p => p.StudentId);
this.HasRequired(p => p.Course)
.WithMany(r => r.Students)
.HasForeignKey(p => p.CourseId);
}
}