VS Community 2015 MVC Template - Cannot access custom model - asp.net

I'm currently learning Asp.NET MVC, I have started with the Ouf of the Box template from Vs2015 but I am having problems getting data from custom table
Goal: My Goal is to add a contact list for the standard ApplicationUser using the following class:
public class UserContact
{
[Key]
public virtual int Id { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ApplicationUser Contact { get; set; }
}
I have also added the following to my Application User:
public virtual ICollection<UserContact> ContactsList { get; set; }
And the following line to my ApplicationDbContext:
public DbSet<UserContact> UserContacts { get; set; }
The problem is that when I try to access the USerContacts table from my custome controller ContactController using
ApplicationDbContext db = new ApplicationDbContext();
var UserId = SomUserID
db.UserContacts.Where(x => x.User == UserId)
The where clause does not get recognised at all. I have useed the commands
enable-migration
add-migration ContactsList
update-database
Which ran with no errors and the table is now in the database. But I am unable to access the table. why? what am I doing wrong?
Please note that according to VS it is as if the .Where function is not available on the DbSet in my case
And linq is imported as this is the standard when adding a new empty controller with Vs2015.
The Database was created during the update-database
But ApplicationDbContext : IdentiyDbContext class does not let me access any other tables including Contact class, so,
when I used in my controller
"db.UserContacts.Where < x => x.User == someID >();"
it doesn recognise what x.User is from the UserContact class.

EDIT: I found a stack overflow post where the user was missing a using statement:
using System.Linq;
DbContext -> DbSet -> Where clause is missing (Entity Framework 6)

Related

I could not connect to database instance created with Entity Framework generated from model

I created a web application and a model. Then I generated a dbcontext class and a database instance. After I built the project, I tried to connect to that database from Server Explorer in Visual Studio, but could not connect.
I tried to test connection but got an error:
This connection cannot be tested because the specified database does not exist or is not visible to the specified user
Whenever I tried to scaffold view or controller I got this error:
Unable to retrieve metadata for ... one or more validation errors were detected during model generation
ModelsTable is based on type TestModel that has no keys defined.
When I created database object in controller class and write query got same error no key defined.
Also made updates on packages and tried again. I think my connection string is correct.
Here is my model.
public class TestModel
{
[Key]
public string ID { get; } = Guid.NewGuid().ToString();
public string AreaName { get; set; }
public bool IsWorking { get; set; }
public string UserName { get; set; }
public DateTimeOffset Time { get; set; }
}
So I could not use scaffolding, Entity Framework and write query.
Here is my dbcontext class.
public class ModelDB : DbContext
{
public ModelDB()
: base("name=ModelDB")
{
}
public DbSet<TestModel> ModelsTable { get; set; }
}
I searched on internet tried founded solutions but did not understand and could not solve. I hope did not ask unnecessary questions. Thanks for your helping.
Are you using Code First? If so I think you need to generate migrations.
In visual studio go to Package Manager Console and run this commands:
Add-Migration "modelClassName"
Update-Database –Verbose
For more information refer to this link: https://msdn.microsoft.com/en-us/library/jj591621(v=vs.113).aspx
You are missing the set; in the field ID.

Creating table Entity Framework Core and SQLite

Using Microsoft.EntityFrameworkCore.SQLite, I'm attempting to create a code level creation of a database, and add a simple row to a table. I get the error, SQLite error: no such table Jumplists.
From last to first, here are the classes
using JumpList_To_Clipboard.Data.Tables;
using Microsoft.EntityFrameworkCore;
namespace JumpList_To_Clipboard.Data
{
public class DataSQLite : IData
{
public const string DATABASE = "data.sqlite";
public DataSQLite()
{
using (var db = new SQLiteDbContext(DATABASE))
{
// Ensure database is created with all changes to tables applied
db.Database.Migrate();
db.JumpLists.Add(new JumpList { Name = "Default" });
db.SaveChanges(); // Exception thrown here
}
}
}
}
The DbContext class
using JumpList_To_Clipboard.Data.Tables;
using Microsoft.EntityFrameworkCore;
namespace JumpList_To_Clipboard.Data
{
class SQLiteDbContext : DbContext
{
readonly string db_path;
public DbSet<JumpList> JumpLists { get; set; }
public DbSet<Group> Groups { get; set; }
public DbSet<Item> Items { get; set; }
public SQLiteDbContext(string database) : base()
{
db_path = database;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(string.Format("Data Source={0}", db_path));
}
}
}
The JumpList class
using System.Collections.Generic;
namespace JumpList_To_Clipboard.Data.Tables
{
public class JumpList
{
public int JumpListId { get; set; }
public string Name { get; set; }
public List<Group> Groups { get; set; }
public List<Item> Items { get; set; }
}
}
The other two classes aren't worth repeating here, and don't give errors.
When I use the firefox sqlite extension to look at the data.sqlite file, none of my three tables are listed.
The command db.DataBase.Migrate says it
Applies any pending migrations for the context to the database.
What are pending migrations? I can't seem to find any documentation anywhere on these.
I'm combining examples from:
https://learn.microsoft.com/en-us/ef/core/get-started/netcore/new-db-sqlite
https://blogs.msdn.microsoft.com/dotnet/2016/09/29/implementing-seeding-custom-conventions-and-interceptors-in-ef-core-1-0/
Edit: If I replace db.Database.Migrate(); with db.Database.EnsureCreated(); it works. From the documentation, Migrate() is the same, but lets you create updates to the table structures, where EnsureCreated() does not. I'm confused.
So,
Microsoft has a serious issue making decent documentation, but I did find a site that has somewhat dated documentation for Learning Entity Framework Core, specifically migrations which is in the link.
At the top, it mentions,
If you have Visual Studio, you can use the Package Manager Console (PMC) to manage migrations.
Which led to the Package Manager Console page which states right at the top, that you need to have:
If you want to use the Package Manager Console to execute migrations command, you need to ensure that the latest version of Microsoft.EntityFrameworkCore.Tools is added to your project.json file.
The problem is, there is no project.json file anywhere in my project (or solution). After some searching, I found that via NuGet, to add Microsoft.EntityFrameworkCore.Tools
Then via Tools > NuGet Package Manager > Package Manager Console I was able to run the add-migration InitialDatabases command. The last part InitialDatabases is the name of the class it creates for you, and sticks in a folder called Migrations at the base of the project.
Now when:
context.Database.Migrate();
is run, all is well!
Try this (worked for me in a project a few months ago, i don't remember why):
public virtual DbSet<JumpList> JumpLists { get; set; }
public virtual DbSet<Group> Groups { get; set; }
public virtual DbSet<Item> Items { get; set; }
Also i had to use LONG instead of INT for classes ID because sqlite uses LONG as default for table ID, so after when you do a CRUD operation it fails because it can't compare/convert/cast LONG(64) to INT(32).

How to access users when Identity project uses EF Core and Class Library uses EF6 with same database

We have a .NET Core project that uses Identity 3 and IdentityDbContext using EF Core for user management. The generated tables are stored in a common SQL server database that is also being used by another project in our solution that is a .NET 4.5.2 Framework DataLayer using EF6.
(Just some more background - the .NET Core project is an authorization server that uses OpenIddict to implement OpenIdConnect and Oauth2 and is configured with Identity so that we can save users to the database and login and authenticate)
Once we've authenticated, we make calls to our API end point. The API talks to a DataLayer that works with EF6. From this project I need to fetch the logged in user and work with users for various queries. Ideally, I wanted to use and extend the same AspNetUsers table.
I am wondering what the recommended approach is here? If I try to generate a User DbContext in the EF6 project I have to add a new migration and the scaffolding wants to create a new table - one that already exists in the database. I am a little unsure about having 2 separate contexts in 2 different projects and how these can "play nice" together.
I have handled similar scenario recently. I followed this approach.
I have a separate Class Library for Data Layer, which has Identity related Repositories/Stores, migrations and DbContext. The DbContext takes connection string from the host project.
.Net Core project has connection string specified in appSettings.json. This connection string points to same database. This project implements IdentityServer3 and acts as Token Service.
.Net 4.5.2 project has connection string specified in web.config . This also points to same database. This app gets token from .net core project and uses that Bearer Token to access other APIs.
I created another project to keep the Entities and this project is referenced in both .net core and .net hosts.
This way i have one common data layer for 2 host projects and 2 different service/business layers for 2 host projects. It is working nicely for me.
As EF 7.0 doesn't support seeding, I have a console app for seeding data into database. Even this console app accesses the same database through Data Layer.
So 3 different projects are accessing same database.
I can't share my code with public. I hope this helps.
I was able to get this to work. The main issue is that I just wanted to access my AspNetUsers table that was generated by Identity 3 in the DotNet Core project in my DotNet 4.51 DataLayer class library project.
I achieved this by creating a User.cs Entity class in the class library EF 6 project and making sure it's properties matched the columns from the Identity 3 generated ApplicationUser.cs class.
User.cs
public class User{
[Key]
public string Id { get; set; }
public int AccessFailedCount { get; set; }
public string ConcurrencyStamp { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public bool LockoutEnabled { get; set; }
public DateTimeOffset? LockoutEnd { get; set; }
public string NormalizedEmail { get; set; }
public string NormalizedUserName { get; set; }
public virtual string PasswordHash { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public virtual string SecurityStamp { get; set; }
public bool TwoFactorEnabled { get; set; }
public string UserName { get; set; }
}
I then set up an EntityConfiguration to map to the AspNetUsers table
UserConfiguration.cs
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
ToTable("AspNetUsers");
}
}
In my DbContext class I added a DbSet for my Users entity:
public virtual IDbSet<User> Users { get; set; }
I then ran the Add-Migration command to scaffold the changes. Once generated, I commented out the code and applied the migration to the database. This generates a row in the __MigrationsHistory table for the AspNetUsers table but doesn't try to recreate the table.
I was then able to successfully talk to the AspNetUsers table from the DataLayer EF6 project :)
Also it seems that I can also extend the AspNetUsers table with custom columns now by adding properties to my User.cs class and doing the migrations in the EF6 Datalayer project.

Extending Identity3 in MVC6

using the latest (current) RC1 of asp.net5 I'm looking at creating a simple relationship between a User entity and a WorkLog entity.
Is it possible to use the ApplicationUser Class from Identity as a starting point and use the ApplicationUser key which is defined as the linking key? I have had problems extending the ApplicationUser in the past and therefore generated a seperate dbcontext (pointing to the same database) and created my own plumbing in order to pass the IdentityUsers Id into my seperate dbcontext. Does anyone have any examples of extending the IdentityDbContext adding foreign key tables mapping to the IdentityUser Class?
Example below
//DBContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<WorkLogItem> WorkLogItems { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
builder.Entity<WorkLogItem>(
e =>
{
e.Property(p => p.id).IsRequired().UseSqlServerIdentityColumn();
});
}
}
//WorkLogItem
public class WorkLogItem
{
public int id { get; set;}
public String UserId { get; set; }
public int Hours { get; set; }
public String Description { get; set; }
}
//ApplicationUser
public class ApplicationUser : IdentityUser
{
public ICollection<WorkLogItem> WorkLogItems { get; set; }
}
Doing what you've asked is expected to work out of the box. You can look at this commit to see the difference between a newly created MVC 6 project with Identity and your schema above.
Registering a user, and refreshing /Home/Index causes WorkLogItems to be added as expected. Note you don't need a separate DB context for this.
public IActionResult Index()
{
var user = _db.Users.Include(p => p.WorkLogItems).FirstOrDefault();
if (user != null)
{
user.WorkLogItems.Add(new WorkLogItem { Description = "New item added" });
_db.SaveChanges();
ViewBag.WorkItems = user.WorkLogItems.ToList();
}
else ViewBag.WorkItems = new WorkLogItem[] { };
return View();
}
The key items to be aware of when you add any collection to an existing entity are;
Make sure you add the migration and update the databse
Make sure you use Include on the query because EF7 does not support Lazy Loading.

Create DB context in different project

There is option to create DB which the DB context not allocated in the same MVC project,
i.e create one MVC in project A and the DB context in In project B which can use the model of model A
The reason is that I want to access to the DB from different project without any dependence
Edit.
I've created this in project A and generate the view and controller by scaffold and its working,now what should I do in project B to access to this DB context?
namespace DiffDBContext2.Models
{
public class Ad
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class AdModelDbContext : DbContext
{
public DbSet<ad> Ad { get; set; }
}
}
I am not sure what do you exactly want. But what I feel is that you want to have data access later as a separate project than your client (mvc). In this case you can have you dbcontext in another project but you need to have connection string in both mvc and data access project. when executing it always request connection string from client.

Resources