Entity Framework Code-First : How to design? - asp.net-mvc

I have a MS-SQL table as shown below.
Users Table
CREATE TABLE [dbo].[Users](
[UserId] [uniqueidentifier] NOT NULL Primary Key,
[UserAccount] [nvarchar](50) NOT NULL Unique,
[Password] [nvarchar](50) NOT NULL,
[UserEmail] [nvarchar](50) NOT NULL,
[JoinDate] [datetime2](7) NOT NULL,
[LoginDate] [datetime2](7) NULL)
Roles Table
CREATE TABLE [dbo].[Roles](
[RoleId] [uniqueidentifier] NOT NULL Primary Key,
[RoleName] [nvarchar](50) NOT NULL Unique,
[Note] [nvarchar](50) NOT NULL,
[RegistDate] [datetime2](7) NOT NULL)
UsersInRoles Table
CREATE TABLE [dbo].[UsersInRoles](
[UserId] [uniqueidentifier] NOT NULL,
[RoleId] [uniqueidentifier] NOT NULL,
[SetDate] [datetime2](7) NOT NULL,
PRIMARY KEY CLUSTERED (
[UserId] ASC,
[RoleId] ASC)WITH (
PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
GO
ALTER TABLE [dbo].[UsersInRoles] WITH CHECK ADD FOREIGN KEY([RoleId]) REFERENCES [dbo].[Roles] ([RoleId]) GO
ALTER TABLE [dbo].[UsersInRoles] WITH CHECK ADD FOREIGN KEY([UserId]) REFERENCES [dbo].[Users] ([UserId]) GO
I'm trying to express in EF Code-First of this.
User Entity Class
public class User
{
public Guid UserId { get; set; }
public string UserAccount { get; set; }
public string Password { get; set; }
public string UserEmail { get; set; }
public DateTime JoinDate { get; set; }
public DateTime LoginDate { get; set; }
}
Role Entity Class
public class Role
{
public Guid RoleId { get; set; }
public string RoleName { get; set; }
public string Note { get; set; }
public DateTime RegistDate { get; set; }
}
UsersInRole Entity Class
public class UsersInRole
{
public Guid UserId { get; set; }
public Guid RoleId { get; set; }
public DateTime SetDate { get; set; }
}
The problem of the foreign key, How should designed UsersInRoles?
Please let me know if there is a better design.

It's not really code first if you are designing your database and then making the code conform, is it? Sounds like you should have a roles collection defined on your User class and then let EntityFramework do the work of building that intermediate table. It will handle the FK relationships.

I haven't tried running the following code, so I aren't 100% sure.
However I would start out with something like ...
in your domain classes
public class User
{
public Guid UserId { get; set; }
public string UserAccount { get; set; }
public string Password { get; set; }
public string UserEmail { get; set; }
public DateTime JoinDate { get; set; }
public DateTime LoginDate { get; set; }
}
public class Role
{
public Guid RoleId { get; set; }
public string RoleName { get; set; }
public string Note { get; set; }
public DateTime RegistDate { get; set; }
}
public class UsersInRole
{
public DateTime SetDate { get; set; }
virtual User User { get; set; }
virtual Role Role { get; set; }
}
in your context you need
public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<UsersInRole> UsersInRoles { get; set; }
optionally you might want to include
public virtual ICollection<UsersInRole> Roles { get; private set; }
in the User class
and/or
public virtual ICollection<UsersInRole> Users { get; private set; }
in the role class
Which will keep the same data structure.

Related

EF core Join two table without primary key column

[Table("User")]
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string UserName { get; set; }
//I should join with User.UserName and UserRoles.UserName
public List<UserRoles> UserRolesList { get; set; }
}
[Table("Role")]
public class Role
{
public int Id { get; set; }
public string RoleKey { get; set; }
public string Description { get; set; }
}
[Table("UserRoles")]
public class UserRoles
{
public int Id { get; set; }
public string UserName { get; set; }
public string RoleKey { get; set; }
}
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<UserRoles> UserRolesList { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
//Getting all users with roles
var usersWithRoles= _dbContext.Users.Include(b => b.UserRolesList).ToList();
I have 3 tables (User,Role and UserRoles), I want to joins User and UserRoles table with UserName column. But EntityFramework not allow doing this with out primary key column. What should I do?
Thanks.
I think you should design the UserRole table like below
[Table("UserRoles")]
public class UserRoles
{
public int Id { get; set; }
public int UserId { get; set; }
public int RoleId { get; set; }
public User User {get; set;}
public Role Role {get;set;}
}
Using thing you can now join with userId and get the user name from user table. Also can join with role table by roleId and can get role key.

Why is entity framework trying to find these non-existant columns?

public partial class User {
public int Id { get; set; }
public Nullable<int> InvoiceAddress_Id { get; set; }
public Nullable<int> MailAddress_Id { get; set; }
public virtual Address Address { get; set; }
public virtual Address Address1 { get; set; }
}
When I try to retrieve user using Linq and Entity framework, I get;
Invalid column name 'Address_Id1'.
Invalid column name 'Address1_Id1'.
Invalid column name 'Address_Id'.
Invalid column name 'Address_Id1'.
I have no idea why it's coming up like that and doing search for any of these columns in the solution gives nothing! I have a feeling it has something to do with foreign keys.
public partial class Address
{
public Address()
{
this.User = new HashSet<User>();
this.User1 = new HashSet<User>();
}
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
public virtual ICollection<Customer> User { get; set; }
public virtual ICollection<Customer> User1 { get; set; }
}
Here is how I'm using entity framework:
CustomDbContext db = new CustomDbContext ();
var user = db.User.First(a => a.Id != 0);
Here's the updated code:
public partial class User
{
public int Id { get; set; }
public Nullable<int> InvoiceAddress_Id { get; set; }
public Nullable<int> MailAddress_Id { get; set; }
public virtual Address InvoiceAddress_ { get; set; }
public virtual Address MailAddress_ { get; set; }
}
Here's the error:
Invalid column name 'Address_Id'.
Invalid column name 'Address_Id1'.
The problem is quite clear: nor your code (attributes, fluent API), neither the EF conventions are configuring the FKs.
If you want to use conventions, you have to adjust the names of the properties and the foreign keys, so that they can be configured. Where you have:
public Nullable<int> InvoiceAddress_Id { get; set; }
public virtual Address Address { get; set; }
You should have:
public Nullable<int> InvoiceAddressId { get; set; }
public virtual Address InvoiceAddress { get; set; }
Note that the FK name is the navigation property name + "Id"
Other option is to implement OnModelCreating of your DbContext and configure the FKs using the fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasOptional(u => u.Address)
.WithMany();
.HasForeingKey(a => a.InvoiceAddres_Id);
}
Or use the [ForeignKey("")] attribute:
The annotation may be placed on the foreign key property and specify the associated navigation property name, or placed on a navigation property and specify the associated foreign key name
I.e.
[ForeignKey("Address")]
public Nullable<int> InvoiceAddress_Id { get; set; }
or
[ForeignKey("InvoiceAddress_Id")]
public virtual Address Address { get; set; }

ASP.Net MVC 1 to many binding doesn't work

I am new to MVC and I've got this annoying problem.
I am doing a small project to understand MVC better.
I am working in a code-first way.
I've created these two classes:
public class Post
{
[Required]
public int ID { get; set; }
[Required]
public string UserName { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Text { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")]
public DateTime Date { get; set; }
[Required]
public PostCategoryType Category { get; set; }
[Required]
public string PictureUrl { get; set; }
[Required]
public string VideoUrl { get; set; }
public virtual List<UserComment> Comments { get; set; }
}
public class UserComment
{
[Required]
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string WebSite { get; set; }
[Required]
public string Comment { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")]
public DateTime Date { get; set; }
}
public class MyStoreDbContext : DbContext
{
public DbSet<Post> Posts { get; set; }
public DbSet<UserComment> UsersComments { get; set; }
}
in order for the classes to be generated into tables at the entity framework I simply added controllers - one for each class and than ran the program and it generated the two tables.
The generated tables at the entity framework looks like this:
CREATE TABLE [dbo].[Posts] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[UserName] NVARCHAR (MAX) NOT NULL,
[Title] NVARCHAR (MAX) NOT NULL,
[Text] NVARCHAR (MAX) NOT NULL,
[Date] DATETIME NOT NULL,
[Category] INT NOT NULL,
[PictureUrl] NVARCHAR (MAX) NOT NULL,
[VideoUrl] NVARCHAR (MAX) NOT NULL,
CONSTRAINT [PK_dbo.Posts] PRIMARY KEY CLUSTERED ([ID] ASC)
);
CREATE TABLE [dbo].[UserComments] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NOT NULL,
[Email] NVARCHAR (MAX) NOT NULL,
[WebSite] NVARCHAR (MAX) NOT NULL,
[Comment] NVARCHAR (MAX) NOT NULL,
[Date] DATETIME NOT NULL,
[Post_ID] INT NULL,
CONSTRAINT [PK_dbo.UserComments] PRIMARY KEY CLUSTERED ([ID] ASC),
CONSTRAINT [FK_dbo.UserComments_dbo.Posts_Post_ID] FOREIGN KEY ([Post_ID]) REFERENCES [dbo].[Posts] ([ID])
);
GO
CREATE NONCLUSTERED INDEX [IX_Post_ID]
ON [dbo].[UserComments]([Post_ID] ASC);
I have a controller which have a data member of :
private MyStoreDbContext db = new MyStoreDbContext ();
in which I want my posts and user comments from.
Now to the problem:
When I access :
foreach(Post post in db.Posts)
{
post.Comments <------ This is always null
}
I've tried inserting a record of post with id 1 for example.
Than I inserted to the UserComments in which the post_id is the 1. (Both manually with VS Server Explorer);
when I try the code above the comments are always null.
I even tried different approach in which I manually inserted at debug time this:
UserComment comment = new UserComment... // Initialization
Post post = new Post.. // Initializing all but Comments
post.Comments = new List<UserComment>();
post.Comments.Add(comment);
db.Comments.Add(comment);
db.Posts.Add(post);
db.SaveChanges();
After all that, each and every post's comments property is null.
What am I missing?
Please help me as it is driving me crazy and accroding to other people's solutions to this problem online is exactly like this I cannot point out the problem.
Thanks in advance to all the helpers!
You need to add ID of Post in the UserComment class, like below:
public class UserComment
{
[Required]
public int ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
public string WebSite { get; set; }
[Required]
public string Comment { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:dd MMM yyyy}")]
public DateTime Date { get; set; }
public int PostID { get; set; }
[ForeignKey("PostID")]
public virtual Post Post { get; set; }
}
Then, Create a instance of Post first, like below:
var newPost = new Post{
UserName = "John",
//
}
db.Posts.Add(newPost );
db.SaveChanges();
After that, create a instance of UserComment, assign the ID of newPost to it, see below:
var comment = new UserComment
{
Name = "Some one",
//
PostID = newPost.ID
}
newPost.Comments.Add(comment);
db.SaveChanges();
Note:
You can learn more about this at below link:
http://codeblog.shawson.co.uk/entity-framework-4-1-code-first-with-one-to-many-relationship-code-example/

ASP.NET MVC & EF5 - Create column type datetime2, Key property

Question 1.
I have created a database in code-first.
[Column(TypeName="datetime2")]
public DateTime RegistDate { get; set; }
In this way, the table is not created.
modelBuilder.Entity<Test>().Property(f => f.RegistDate).HasColumnType("datetime2");
(In OnModelCreating method)
I can be resolved by using Fluent API.
To create a column format datetime2, is there a way only a Fluent API?
Question 2.
I have a domain model as follows.
User Entity Class
public class User
{
public Guid UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string UserEmail { get; set; }
public DateTime JoinDate { get; set; }
public DateTime LoginDate { get; set; }
public virtual ICollection<UsersInRole> UsersInRoles { get; set; }
}
Role Entity Class
public class Role
{
public Guid RoleId { get; set; }
public string RoleName { get; set; }
public DateTime CreateDate { get; set; }
public virtual ICollection<UsersInRole> UsersInRoles { get; set; }
}
UsersInRole Entity Class
public class UsersInRole
{
public Guid UserId { get; set; }
public Guid RoleId { get; set; }
public DateTime SetDate { get; set; }
[ForeignKey("UserId")]
public User User { get; set; }
[ForeignKey("RoleId")]
public Role Role { get; set; }
}
This build, the following error will occur
One or more validation errors were detected during model generation:
\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'UsersInRole' has no key defined. Define the key for this EntityType.
\tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'UsersInRoles' is based on type 'UsersInRole' that has no keys defined.
I do not want to add another property Id.
Also, I can not use the [Key] UserId, to RoleId.
There are no other solutions?

EF 4 lazy loading

Having problem in displaying relational properties b/w two tables having one(company) to many(package_master) relationship
Action
public ViewResult Index()
{
var companies = db.companies.Include(c => c.aspnet_Users)
.Include(c=>c.package_master);
return View(companies.ToList());
}
EntitySet
public partial class company
{
public company()
{
this.package_master = new HashSet<package_master>();
}
public int company_id { get; set; }
public string name { get; set; }
public string address { get; set; }
public string phone { get; set; }
public string fax { get; set; }
public Nullable<System.Guid> sen_sup { get; set; }
public virtual aspnet_Users aspnet_Users { get; set; }
public virtual ICollection<package_master> package_master { get; set; }
}
When I type Model.aspnet_Users.property1 everything works fine(intellisense) but now I also want to diaplay properties from packege_master(no intellisense)(foreign key table=package_master having client_id as foreign key, public key table=company having company_id as primary key)
package_master is a collection. You cannot access member properties of package_master entities directly like: Model.package_master.XXX. You must iterate the collection to get access to entities.

Resources