I use VS 2015 and Entity Framework 6.2.0.
I have two tables tblUsers and tblFields in sqlServer.
I create two models related to my tables:
[Table("tblUsers")]
public class Users
{
[Key]
public string UserName { get; set; }
public string UserPassword { get; set; }
public DateTime RegisterDateTime { get; set; }
public string FieldId { get; set; }
public float Score { get; set; }
}
[Table("tblFields")]
public class Fields
{
[Key]
public string FieldID { get; set; }
public string FieldTitle { get; set; }
}
So, in my DataAccessLayer, I have:
public class Dal : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Users>().ToTable("tblUsers");
modelBuilder.Entity<Fields>().ToTable("tblFields");
base.OnModelCreating(modelBuilder);
}
public DbSet<Users> UsersSet { get; set; }
public DbSet<Fields> FieldsSet { get; set; }
}
When I use the following code in BusinessLayer to get Users Data:
public List<Users> GetAllUsers()
{
Dal dal = new Dal();
return dal.UsersSet.ToList();
}
No users are return!
Where is the problem?
I create a database and it's tables. Then I created my project that used from database. The problem is here!
Solution: I deleted all tables from database and then I run my application. Application created all tables again and problem is solved.
Related
I have view in SQL called ViewTest.
In code I have this model
[Table("dbo.ViewTest")]
public class ViewTest
{
public int Id { get; set; }
public int EmployeeID { get; set; }
public string PreferredName { get; set; }
public string EmailPrimaryWork { get; set; }
public string GeoCoverage { get; set; }
public string Role { get; set; }
public bool? LeftEmpFlag { get; set; }
}
In configuration file:
public virtual IDbSet<ViewTest> ViewTests { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ViewConfiguration());
}
public class ViewConfiguration : EntityTypeConfiguration<ViewTest>
{
public ViewConfiguration()
{
this.HasKey(t => t.Id);
this.ToTable("ViewTest");
}
}
I want to have connection like this one ViewTests.Where(....) ,but when I tried to do like this way I have error There is already an object named 'ViewTest' in the database..This means entity framework try to create new Table and I don`t want this.I want to access this view only!
Well, it is code first so you should probably create your view in code. If that is not possible, then you need to tell EF not to create the table by commenting that line out of the Up() method on the migration. Once you update-database EF will have it in the metadata and you should be good to go.
I am new to Entity Framework and Asp.NET, and therefore, struggling with creating database relationships within the Entity Framework.
I have two SQLite tables (Ticket and User) and have setup my entity models as follows:
public class Users
{
[ForeignKey("id")]
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public virtual ICollection<Tickets> Tickets { get; set; }
}
public class Tickets
{
public int id { get; set; }
public string summary { get; set; }
public string description { get; set; }
public string c_location { get; set; }
public string c_store_device { get; set; }
public string category { get; set; }
public DateTime? created_at { get; set; }
public DateTime? closed_at { get; set; }
public int priority { get; set; }
public int? assigned_to { get; set; }
public DateTime? due_at { get; set; }
public DateTime? updated_at { get; set; }
public string status { get; set; }
public virtual Users Users { get; set; }
}
I am trying to use Entity Framework 7 to export an IEnumerable<Tickets> that includes the User assigned to each Ticket.
I have tried to create my model relationship in MyDBContext as a single User can have multiple Tickets, and also has a foreign key associated in my Sqlite database (Tickets.assigned_to = User.id):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Users - > many Tickets
modelBuilder.Entity<Users>()
.HasMany(p => p.Tickets)
.WithOne(e => e.Users)
.HasForeignKey(p => p.assigned_to);
}
My result ends up with Ticket data being exported, but against every ticket I see a null value for User:
[{"id":10002,...,"Users":null}]
When I use .Include() within my Repository to include each User like this:
public IEnumerable<Tickets> GetAll()
{
return _db.Tickets.Include(t => t.Users).ToList();
}
It results in the error
HTTP Error 502.3 - Bad Gateway
The specified CGI application encountered an error and the server terminated the process.
What I'm trying to retrieve is data that looks like:
{"Ticket";[{"id":10002,..."status":"closed"}],"Users":[{"id":"1"..."email":"johndoe#someplace.com"}]}
I know it probably has something to do with my relationship model, but I cannot work out what I am doing wrong.
First you should really derive your Users from IdentityUser. It helps when trying to wire up the relationship, but I will give you the answer based on your current models. Your ForeignKey property should be on the child entity. By naming conventions, which is what EF uses by default, your public Users Users works better if you put a public int UsersId. Then essentially what EF will do is from your public Users Users it will go to the Users table. Then it looks for the ForeignKey which is set to Id, so now we are in the Users Table looking at the id property. Then it looks for the naming convention UsersId and if it sees it, it will set that property to the value that it saw from the Users Table Id column.
Try using this
public class Users
{
public int id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public virtual ICollection<Tickets> Tickets { get; set; }
}
public class Tickets
{
public int id { get; set; }
public string summary { get; set; }
public string description { get; set; }
public string c_location { get; set; }
public string c_store_device { get; set; }
public string category { get; set; }
public DateTime? created_at { get; set; }
public DateTime? closed_at { get; set; }
public int priority { get; set; }
public DateTime? due_at { get; set; }
public DateTime? updated_at { get; set; }
public string status { get; set; }
[ForeignKey("Id")]
public int UsersId { get; set; }
public virtual Users Users { get; set; }
}
and for your Fluent API configuring
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Users - > many Tickets
modelBuilder.Entity<Users>()
.HasMany(p => p.Tickets)
.WithOne();
}
Now all that does is create the relationship. In order to view the specific items you want to view, use a ViewModel. So, pull the two lists you want from where you want. Then use logic to separate the list how you want them to display.
public class UsersViewModel()
{
public UsersViewModel(Users user, List<Tickets> tickets)
{
this.first_name = user.first_name;
this.last_name = user.last_name;
this.email = user.email;
this.Tickets = new List<Tickets>();
foreach(var ticket in tickets)
{
if(ticket.UserId == user.Id)
{
this.Tickets.Add(ticket)
}
}
}
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public List<Tickets> Tickets { get; set;}
}
then in your controller make your list
public IActionResult Index()
{
var usersList = _repository.Users.ToList();
var ticketsList = _repository.Tickets.ToList();
var model = new List<UsersViewModel>();
foreach(var user in usersList)
{
var listItem = new UsersViewModel(user, ticketsList);
model.Add(listItem);
}
return View(model);
}
or use a Linq query
public IActionResult Index()
{
var usersList = _repository.Users.ToList();
var model = new List<UsersViewModel>();
foreach(var user in usersList)
{
var ticketsList = from x in _repository.Tickets where x.UserId.Equals(user.Id) select x;
var listItem = new UsersViewModel(user, ticketsList);
model.Add(listItem);
}
return View(model);
}
then at the top of your view you should have
#model IEnumerable<UsersViewModel>
I am trying to migrate a MVC3 Application to MVC5. I have Used these Articles:
http://www.asp.net/identity/overview/migrations/migrating-an-existing-website-from-sql-membership-to-aspnet-identity
http://www.codeproject.com/Articles/682113/Extending-Identity-Accounts-and-Implementing-Role
The old Application use the Database First Model (modeled with the EDMX file).
When I try to update the Role of a User I got following Error:
Additional information: The entity type IdentityRole is not part of the model for the current context.
In this Method (um.AddToRole):
public bool AddUserToRole(string userId, string roleName)
{
var um = new UserManager<AspNetUsers>(
new UserStore<AspNetUsers>(new Entities()));
var idResult = um.AddToRole(userId, roleName);
return idResult.Succeeded;
}
How Can I tell the UserManager to Use the AspNetRoles Class?
Best Regards,
Marko
AspNetUsers
namespace NursingHome.Models
{
using System;
using System.Collections.Generic;
public partial class AspNetUsers
{
public AspNetUsers()
{
this.AspNetUserClaims = new HashSet<AspNetUserClaims>();
this.AspNetUserLogins = new HashSet<AspNetUserLogins>();
this.NursingHome = new HashSet<NursingHome>();
this.AspNetRoles = new HashSet<AspNetRoles>();
}
//public string Id { get; set; }
//public string UserName { get; set; }
//public string PasswordHash { get; set; }
//public string SecurityStamp { get; set; }
public string Discriminator { get; set; }
public System.Guid ApplicationId { get; set; }
public string LegacyPasswordHash { get; set; }
public string LoweredUserName { get; set; }
public string MobileAlias { get; set; }
public bool IsAnonymous { get; set; }
public System.DateTime LastActivityDate { get; set; }
public string MobilePIN { get; set; }
public string Email { get; set; }
public string LoweredEmail { get; set; }
public string PasswordQuestion { get; set; }
public string PasswordAnswer { get; set; }
public bool IsApproved { get; set; }
public bool IsLockedOut { get; set; }
public System.DateTime CreateDate { get; set; }
public System.DateTime LastLoginDate { get; set; }
public System.DateTime LastPasswordChangedDate { get; set; }
public System.DateTime LastLockoutDate { get; set; }
public int FailedPasswordAttemptCount { get; set; }
public System.DateTime FailedPasswordAttemptWindowStart { get; set; }
public int FailedPasswordAnswerAttemptCount { get; set; }
public System.DateTime FailedPasswordAnswerAttemptWindowStart { get; set; }
public string Comment { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<AspNetUserClaims> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetUserLogins> AspNetUserLogins { get; set; }
public virtual ICollection<NursingHome> NursingHome { get; set; }
public virtual ICollection<AspNetRoles> AspNetRoles { get; set; }
}
}
AspNetUsers Extension
public partial class AspNetUsers : IdentityUser
{
}
AspNetRoles
public partial class AspNetRoles
{
public AspNetRoles()
{
this.AspNetUsers = new HashSet<AspNetUsers>();
}
//public string Id { get; set; }
//public string Name { get; set; }
public virtual ICollection<AspNetUsers> AspNetUsers { get; set; }
}
AspNetRoles Extension
public partial class AspNetRoles : IdentityRole
{
public AspNetRoles(string name)
: base(name)
{
}
}
DB Context Extension
public partial class Entities : IdentityDbContext<AspNetUsers>
{
public Entities()
: base("NursingHomesEntities")
{
}
}
Update
Installed Packages
Install-Package Microsoft.AspNet.Identity.EntityFramework
Install-Package Microsoft.AspNet.Identity.Core
Install-Package EntityFramework
Install-Package Microsoft.AspNet.Mvc
Install-Package Twitter.Bootstrap.MVC
Install-Package Microsoft.AspNet.Identity.Samples -Pre
Install-Package FontAwesome
Next Steps
EDMX File added (from database created)
Added one table with reference to AspNetUser.
Now I get following error:
Model compatibility cannot be checked because the DbContext instance was not created using Code First patterns. DbContext instances created from an ObjectContext or using an EDMX file cannot be checked for compatibility.
Is it not possible to use edmx file and mvc5 together?
First I recommend to use, a new asp.net identity 2.0 beta: https://www.nuget.org/packages/Microsoft.AspNet.Identity.Core/2.0.0-beta1
It is better and more flexible to override and use. You can get some information, samples and other things here: http://blogs.msdn.com/b/webdev/archive/2014/02/11/announcing-preview-of-microsoft-aspnet-identity-2-0-0-beta1.aspx
I can't reproduce this error, but probably is in the mapping configuration, a entity framework error and not a asp.net MVC error..
You need to take some care, replace all uses of dbcontext in your app, there is a topic to take a look to avoid this error: The entity type <type> is not part of the model for the current context
If is still not working, try make some tests and experiences or add more information here.
As far as i know, i have two way to implement many-to-many relation in asp.net mvc using code-first.
1- Fluent Api
public class HrPerson
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HrPersonTitle> HrPersonTitle { get; set; }
}
public class HrPersonTitle
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<HrPerson> HrPerson { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<HrPerson>()
.HasMany(s => s.HrPersonTitle)
.WithMany(c => c.HrPerson)
.Map(t =>
{
t.MapLeftKey("HrPersonId")
.MapRightKey("HrPersonTitleId")
.ToTable("HrMapPersonTitle");
});
}
2-Custom Mapping Table
public class HrPerson
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HrMapPersonTitle> HrMapPersonTitle { get; set; }
}
public class HrPersonTitle
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<HrMapPersonTitle> HrMapPersonTitle { get; set; }
}
public class HrMapPersonTitle
{
public int Id { get; set; }
public int HrPersonId { get; set; }
public int HrPersonTitleId { get; set; }
public virtual HrPerson HrPerson { get; set; }
public virtual HrPersonTitle HrPersonTitle { get; set; }
public string Note { get; set; }
public bool Deleted { get; set; }
}
My questions:
If i choose second way, i am not able to reach HrPersonTitle.Name property from HrPerson model in the view. How can i reach the properties ?
If i choose the first way i can reach the HrPersonTitle.Name but i am not able to add more property in the map file ? How can i add more properties?
Regards.
When you create a M2M without a payload (just the foreign key relationships, no extra data), EF collapses the relationship so that you can query directly without having to explicitly go through the join table. However, if you need a payload, then EF can no longer manage the relationship in this way.
So, if you want to get the title, you have to go through HrMapPersonTitle:
#foreach (var title in Model.HrMapPersonTitle)
{
#title.HrPersonTitle.Name
}
Both these methods seem overkill maybe. I don't know your full intentions however I implement this all the time at work and I use the following:
public class HrPerson
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HrPersonTitle> HrPersonTitles { get; set; }
}
public class HrPersonTitle
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<HrPerson> HrPersons { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<HrPerson>()
.HasMany(s => s.HrPersonTitles)
.WithMany(c => c.HrPersons);
}
If you are using code first and you try and access either mapping within the DbContext it should Lazy Load your information and every property should be accessible.
I do have one question though. Are you sure it should be many to many, do they really have multiple titles?
I want to create large user table (advance User Profile) and save user's data in my database context. So, I don't want to use 2 DbContexts in my project. When users register to site, they data (UserName, Password etc.) stores my own User table. My classes are like this:
public class ModelBase
{
public int Id { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastUpdateDate { get; set; }
}
public class User : ModelBase
{
public string UserName { get; set; }
public string Password{ get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public DateTime BirthDate { get; set; }
public string Specialty { get; set; }
}
public class News : ModelBase
{
public int UserId { get; set; }
public string Title { get; set; }
...
}
....
Context is so:
public class MyDBContext : DbContext
{
public MyDBContext()
{
Database.SetInitializer<MyDBContext>(new MyDBContextInitializer());
}
public DbSet<User> UserSet { get; set; }
public DbSet<News> NewsSet { get; set; }
public DbSet<Project> ProjectSet { get; set; }
public DbSet<Section> SectionSet { get; set; }
....
}
class MyDBContextInitializer : DropCreateDatabaseIfModelChanges<MyDBContext>
{
protected override void Seed(MyDBContext context)
{
base.Seed(context);
}
}
I replaced DbContext name with mine and changed connection name in default SimpleMembershipInitializer class like this:
....
Database.SetInitializer<MyDBContext>(null);
try
{
using (var context = new MyDBContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("MyDBContextConnection", "User", "Id", "UserName", autoCreateTables: true);
....
Finally, I changed RegisterModel and WebSecurity.CreateUserAndAccount() suitable my User class. But, it does not work.
How can I use my own User table for register to site?
You can have Asp.net Membership and your complex classes connected together.
with this approach you will save so much time because asp.net membership is much more robust(you don't need to think about Role and User management) and sure you can make use of existing open source project like this and add it to your project with minimum effort of time.
Then your class will have structure like :
public class CustomUserDetail : ModelBase
{
public string UserName { get; set; } // what you really need is this to be unique for each user in you data base
// public string Password{ get; set; } handled by asp.net Membership
public string FullName { get; set; }
// public string Email { get; set; } handled by asp.net Membership
public DateTime BirthDate { get; set; }
public string Specialty { get; set; }
}
Then you can can add extension method to IPrincipal like :
public static CustomUserDetail CustomUserDetail (this IPrincipal principal)
{
var repository = new YourUserDetailRepository();
return repository.GetCurrentUserDetail();
}
and finnaly in your code easily use
<p> #User.CustomUserDetail.FullName </p>