Many to many with extra foreign key? - asp.net

I want to generate a junction table between user and post and I want to have the userId in the post table.
I have this code
public class Post
{
public Post()
{
this.ApplicationUser = new HashSet<ApplicationUser>();
}
public int PostId { get; set; }
public string Message { get; set; }
public DateTime MessageDate { get; set; }
public virtual ApplicationUser User { get; set; } //this is the problem
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }
}
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public ApplicationUser()
{
this.Posts = new HashSet<Post>();
}
public virtual ICollection<Post> Posts { get; set; }
}
I get the extra junction table and many-to-many relation between user and post. But this is wrong.
public virtual ApplicationUser User { get; set; }
This generates two UserId in the post table (applicationUser_id and User_id) and Post_PostId in the User table. I just want one extra field in the Post table, FK UserId.
I want three tables like this
Post
PostId
Message
Date
UserId FK
User
UserId
And the rest of the fields in asp.net identity user
UserPosts
UserId
PostId

User table
public partial class User
{
public User()
{
this.Posts = new HashSet<Post>();
this.UserPosts = new HashSet<UserPost>();
}
public int UserId { get; set; }
public string Username { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public virtual ICollection<UserPost> UserPosts { get; set; }
}
Post table
public partial class Post
{
public Post()
{
this.UserPosts = new HashSet<UserPost>();
}
public int PostId { get; set; }
public string Message { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public Nullable<int> UserId { get; set; }
public virtual User User { get; set; }
public virtual ICollection<UserPost> UserPosts { get; set; }
}
and your mapping table, like this
your column 1) Id (pk), 2) UserId (fk) 3) PostId (fk)
using entity framework table have one primary key necessary.
UserPost table
public partial class UserPost
{
public int Id { get; set; }
public Nullable<int> UserId { get; set; }
public Nullable<int> PostId { get; set; }
public virtual Post Post { get; set; }
public virtual User User { get; set; }
}
Updated Code
modelBuilder.Entity<Post>().ToTable("userid table name");
this line add in below method of this class ApplicationDbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}

Related

The DELETE statement conflicted with a REFERENCE constraint

I have the following entities.
public class GroupUser
{
public long Id { get; set; }
public Group Group { get; set; }
public long GroupId { get; set; }
public string UserId { get; set; }
public User User { get; set; }
}
public class User : IdentityUser
{
public List<GroupUser> GroupUsers { get; set; }
}
public class Group
{
public long Id { get; set; }
public List<GroupUser> GroupUsers { get; set; }
}
I get the delete The DELETE statement conflicted with the REFERENCE constraint "FK_GroupUsers_AspNetUsers_UserId". The conflict occurred in database "db", table "dbo.GroupUsers", column 'UserId' when I try to delete a user even though I make sure i delete existing entities referencing the id of the user before actually deleting the user like below;
var user = await _userManager.FindByEmailAsync(email);
var groupUsers = _context.GroupUsers.Where(c => c.UserId == user.Id);
_context.RemoveRange(groupUsers);
await _context.SaveChangesAsync();
_context.Remove(user);
await _context.SaveChangesAsync();

Sqlite/SQLServer provider differences

I have some troubles using sqlite provider to write integration tests.
If I attach a tree of entities to my DbContext, I get relations broken (the same thing with SqlServer provider works).
See sample for more information.
For precision, the PK of the 3 tables are Id + TenantId. TenantId is Set only in the SaveChangesAsync method, depending on the connected User.
If I want it to work on sqlite, I have to set the TenantId on the 3 objects before attaching them to the context... Why is this different with SQL Server provider ?
public class Store {
public int Id { get; set; }
public int TenantId { get; set; }
public List<Product> Products { get; set; }
}
public class Product {
public int Id { get; set; }
public int TenantId { get; set; }
public Store Store { get; set; }
public int StoreId { get; set; }
public Category Category { get; set; }
public int CategoryId { get; set; }
}
public class Category {
public int Id { get; set; }
public int TenantId { get; set; }
public List<Product> Products { get; set; }
}
[Test]
public void Test_Create(){
var store = new Store();
store.Products = new List<Product>();
var product = new Product();
product.Category = new Category();
store.Products.Add(product);
dbContext.Stores.Add(store);
// fails, product is detached from the Store after attaching to DbContext
Assert.Single(store.Products);
}

How to extend Application User to hold a collection of orders?

I'm trying to extend Application User (using Code-First) to hold a collection of orders, but I'm getting errors.
My Order class is
public class Order
{
public Order()
{
OrderDetails = new HashSet<OrderDetails>();
}
public int ID { get; set; }
public DateTime OrderDate { get; set; }
public string UserId { get; set; }
public bool IsDelivered { get; set; }
public bool IsReturned { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ICollection<OrderDetails> OrderDetails { get; set; }
}
And I'm trying to extend Application user like this
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Profession { get; set; }
public string TaxAuthority { get; set; }
public string TaxNumber { get; set; }
public string Address { get; set; }
public string PostalCode { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string Country { get; set; }
public string Phone { get; set; }
public string MobilePhone { get; set; }
public bool NewsLetterSubscribe { get; set; } = false;
public DateTime TimeStamp { get; set; } = DateTime.Now;
public ICollection<Order> Orders { get; set; }
}
And I'm getting the following errors:
QCMS.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
QCMS.Models.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.
Can you please help me to solve this problem?
UPDATE:
I'm using two db contexts. The one provided for Individual User Account (when the project is first created) and a second one named "qvModel" that is for all other database classes of my project.
public partial class qvModel : DbContext
{
public qvModel()
: base("name=qvModel")
{
}
//APPSETTINGS
public virtual DbSet<AdminLog> AdminLog { get; set; }
public virtual DbSet<WebLog> WebLog { get; set; }
//LANGUAGES
public virtual DbSet<Language> Languages { get; set; }
.
.
.
public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<OrderDetails> OrderDetails { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Precision attribute for decimals
Precision.ConfigureModelBuilder(modelBuilder);
modelBuilder.Entity<Language>()
.HasMany(e => e.Brochures)
.WithRequired(e => e.Language)
.WillCascadeOnDelete(true);
.
.
.
modelBuilder.Entity<Order>()
.HasMany(c => c.OrderDetails)
.WithRequired(c => c.Order)
.WillCascadeOnDelete(true);
modelBuilder.Entity<ApplicationUser>()
.HasMany(c => c.Orders)
.WithRequired(c => c.User)
.WillCascadeOnDelete(true);
base.OnModelCreating(modelBuilder);
}
}
I found a solution that is very simple.
The solution is to inherit from IdentityDbContext like this
public class qvModel : IdentityDbContext<ApplicationUser>
{
public qvModel()
: base("name=qvModel")
{
}
I was also missing the following line from OnModelCreating
base.OnModelCreating(modelBuilder);
After these changes, my migration is working and I stopped getting the errors I mentioned.

Nested entity models query issue

i have 3 nested models: ApplicationUser(from entity framework), City and State.
ApplicationUser has city as foreign key and city has state as foreign key.
When I query a user, i get a user with all of its attributes including City as a related model but when i lookup into city, the related model State is null, all the others attributes are ok. Any clue?
This is StateModels
public class StateModels
{
public int Id { get; set; }
public string State { get; set; }
public string Abbreviation { get; set; }
}
This is CityModels
public class CityModels
{
public int Id { get; set; }
public string City { get; set; }
public int ZipCode { get; set; }
public virtual StateModels State { get; set; }
}
And this is ApplicationUser
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string CompanyName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public virtual CityModels City { get; set; }
public string CompanyPhone { get; set; }
public string CompanyFax { get; set; }
public bool Validated { get; set; }
public bool Staff { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
This is how i try to get to the state object
ApplicationUser applicationUser = db.Users.Find(idUser);
var city = applicationUser.City; //object city is ok
var state = city.State; // this field is null, all others attributes are ok
In the db, all city registers have state id reference
Try this. db.Users.Find(idUser).Include(u=>u.City).Include(u=>u.City.State) and make sure you have all foreign keys are properly set.

One to Many Assosiation without a collection on many Side EF

I have a BaseEntity Like This :
public class BaseEntity<T>
{
public BaseEntity()
{
this.createdDate = System.DateTime.Now;
this.updatetdDate = System.DateTime.Now;
}
[System.ComponentModel.DataAnnotations.Key]
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.Schema.Column("ID")]
[System.ComponentModel.DataAnnotations.Schema.
DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public T id { get; set; }
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.Schema.ForeignKey("Created_by")]
public virtual BonchaghWebApplication.Models.Core.User createdBy { get; set; }
[System.ComponentModel.DataAnnotations.Required]
[System.ComponentModel.DataAnnotations.Schema.ForeignKey("Updated_by")]
public virtual BonchaghWebApplication.Models.Core.User updatedBy { get; set; }
[System.ComponentModel.DataAnnotations.Required]
public DateTime createdDate { get; set; }
[System.ComponentModel.DataAnnotations.Required]
public DateTime updatetdDate { get; set; }
}
}
and another like this :
[System.ComponentModel.DataAnnotations.Schema.Table("App_User")]
public class User:BaseEntity<long>
{
public String userName { get; set; }
public String password { get; set; }
}
and these two have one to many relation, I don't need a collection on user side, I say that the record saved by a user and it doesn't matter the user save witch records

Resources