Getting error trying to seed data using EF6 Code First - entity-framework

The models looks like this
public class Account : BaseEntity
{
public string AccountNumber { get; set; }
public string AccountTitle { get; set; }
public decimal CurrentBalance { get; set; }
public AccountStatus AccountStatus { get; set; }
[ForeignKey("UserId")]
public string UserId { get; set; }
public virtual User User { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }
}
public enum AccountStatus
{
Active = 0,
InActive = 1
}
public class User : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string ProfilePicUrl { get; set; }
public virtual Account Account { get; set; }
}
public class Transaction : BaseEntity
{
public TransactionType TransactionType { get; set; }
public DateTime TransactionDate { get; set; }
public decimal TransactionAmount { get; set; }
public virtual Account Account { get; set; }
}
public enum TransactionType
{
Deposit = 0,
Withdraw = 1
}
So technically User has One account and Account have one or many Transactions
i am seeding data like below
Basically there are 3 users, 2 of them have accounts associated with them
public class BBBankContext : DbContext
{
public BBBankContext(DbContextOptions<BBBankContext> options) : base(options) { }
public DbSet<User> Users { get; set; }
public DbSet<Account> Accounts { get; set; }
public DbSet<Transaction> Transactions { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// modelBuilder.Entity<User>()
//.HasOne<Account>(s => s.Account)
//.WithOne(ad => ad.User)
//.HasForeignKey<Account>(ad => ad.UserId);
modelBuilder.Entity<User>(b =>
{
b.HasData(new User
{
Id = "2a2615d0-1c0d-4b9c-b41b-cc01aeb35919",
FirstName = "Raas",
LastName = "Masood",
Email = "admin#patternstech.com",
ProfilePicUrl = "",
});
b.HasData(new User
{
Id = "b6111852-a1e8-4757-9820-70b8c20e1ff0",
FirstName = "Ali",
LastName = "Taj",
Email = "malitaj-dev#outlook.com",
ProfilePicUrl = ""
});
b.HasData(new User
{
Id = "582ebb0b-f9e0-4385-8787-37bd337f18b7",
FirstName = "Salman",
LastName = "Taj",
Email = "salman-dev#outlook.com",
ProfilePicUrl = ""
});
});
modelBuilder.Entity<Account>(b =>
{
b.HasData(new Account
{
Id = "37846734-172e-4149-8cec-6f43d1eb3f60",
AccountNumber = "0001-1001",
AccountTitle = "Ali Taj",
CurrentBalance = 2055M,
AccountStatus = AccountStatus.Active,
UserId = "b6111852-a1e8-4757-9820 -70b8c20e1ff0"
});
b.HasData(new Account
{
Id = "2f115781-c0d2-4f98-a70b-0bc4ed01d780",
AccountNumber = "0002-2002",
AccountTitle = "Salman Taj",
CurrentBalance = 545M,
AccountStatus = AccountStatus.Active,
UserId = "582ebb0b-f9e0-4385-8787-37bd337f18b7"
});
});
modelBuilder.Entity<Transaction>().HasData(
new
{
Id = Guid.NewGuid().ToString(),
AccountId = "37846734-172e-4149-8cec-6f43d1eb3f60",
TransactionAmount = 1000M,
TransactionDate = DateTime.Now,
TransactionType = TransactionType.Deposit
},
new
.....
after adding migration and running "Update-Database" i am getting error
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Accounts_Users_UserId". The conflict occurred in database "BBBankDB", table "dbo.Users", column 'Id'.
Spent many hours tyring to figure this out :( what am i doing wrong ?

I think the problem is you have a wrong UserId in this seed.
b.HasData(new Account
{
Id = "37846734-172e-4149-8cec-6f43d1eb3f60",
AccountNumber = "0001-1001",
AccountTitle = "Ali Taj",
CurrentBalance = 2055M,
AccountStatus = AccountStatus.Active,
UserId = "b6111852-a1e8-4757-9820 -70b8c20e1ff0"
// ^
// Here
});
Remove this additional space and your error will be gone.
UserId = "b6111852-a1e8-4757-9820-70b8c20e1ff0"

Related

Entity Framwork Update many to many

I am new to ef core. I am trying to implement many to many .
Here is my DBContext
public class MaxCiSDbContext : DbContext
{
public DbSet<Job> Jobs { get; set; }
public DbSet<Staff> Staffs { get; set; }
public MaxCiSDbContext(DbContextOptions<MaxCiSDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Job>()
.HasMany(t => t.Staffs)
.WithMany(t => t.Jobs);
base.OnModelCreating(modelBuilder);
}
}
and Here is my Staff Class
public class Staff
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Address { get; set; }
//Navigation
public virtual ICollection<Job> Jobs { get; set; }
}
Here is my Job Class
public class Job
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string State { get; set; }
public string ClientOrderNumber { get; set; }
public string StartDate { get; set; }
public string DueDate { get; set; }
public string CompletedDate { get; set; }
public string ClientId { get; set; }
public string ManagerId { get; set; }
public string PartnerId { get; set; }
//Navigation
public virtual ICollection <Staff> Staffs { get; set; }
}
I Call an API which returns a XmlDocument, I read that document and update database.
Here is how I deal with xmldocument.
//Fetch Current Jobs and populate to DB
XmlDocument apiresults = JobMethods.GetCurrent();
XmlNodeList nodes = apiresults.DocumentElement.SelectNodes("/Response/Jobs/Job");
foreach (XmlNode node in nodes)
{
Job MaxCiSJob = new Job()
{
Id = node.SelectSingleNode("ID").InnerText,
Name = node.SelectSingleNode("Name").InnerText,
Description = node.SelectSingleNode("Description").InnerText,
State = node.SelectSingleNode("State").InnerText,
ClientOrderNumber = node.SelectSingleNode("ClientOrderNumber").InnerText,
StartDate = node.SelectSingleNode("StartDate").InnerText,
DueDate = node.SelectSingleNode("DueDate") != null ? node.SelectSingleNode("DueDate").InnerText : "",
CompletedDate = node.SelectSingleNode("CompletedDate") != null ? node.SelectSingleNode("CompletedDate").InnerText : "",
ClientId = node.SelectSingleNode("Client/ID").InnerText,
ManagerId = node.SelectSingleNode("Manager/ID") != null ? node.SelectSingleNode("Manager/ID").InnerText : "",
PartnerId = node.SelectSingleNode("Partner") != null ? node.SelectSingleNode("Partner").InnerText : ""
};
XmlNodeList Assigned = node.SelectNodes("Assigned/Staff");
MaxCiSJob.Staffs = new Collection<Staff>();
foreach (XmlNode staffNode in Assigned)
{
var staffId = staffNode.SelectSingleNode("ID").InnerText;
var staff = _db.Staffs.Find(staffId);
if(staff != null)
{
MaxCiSJob.Staffs.Add(staff);
}
}
if (_db.Jobs.Find(MaxCiSJob.Id) == null)
{
//Insert Record
_db.Jobs.Add(MaxCiSJob);
}
else
{
// UPDATE recorde
_db.Jobs.Update(MaxCiSJob);
}
}
_db.SaveChanges();
}
Everything works well when I run the program for the first time(The linking table ,"JobStaff", is empty) but when I run the Program for the second time I get an excetpion:
SqlException: Violation of PRIMARY KEY constraint 'PK_JobStaff'. Cannot insert duplicate key in object 'dbo.JobStaff'. The duplicate key value is (J14995, 557898).
Can someone please help me on how can I resolve this issue.
Running your code EF core wants to add entities anyway. Because your entities are not attached.
Try this code:
//Fetch Current Jobs and populate to DB
XmlDocument apiresults = JobMethods.GetCurrent();
XmlNodeList nodes = apiresults.DocumentElement.SelectNodes("/Response/Jobs/Job");
foreach (XmlNode node in nodes)
{
var id = node.SelectSingleNode("ID").InnerText;
Job MaxCiSJob = _db.Jobs.Find(id);
if (MaxCiSJob == null)
{
MaxCiSJob = new Job() { Id = id };
_db.Jobs.Add(MaxCiSJob);
}
MaxCiSJob.Name = node.SelectSingleNode("Name").InnerText;
MaxCiSJob.Description = node.SelectSingleNode("Description").InnerText;
MaxCiSJob.State = node.SelectSingleNode("State").InnerText;
MaxCiSJob.ClientOrderNumber = node.SelectSingleNode("ClientOrderNumber").InnerText;
MaxCiSJob.StartDate = node.SelectSingleNode("StartDate").InnerText;
MaxCiSJob.DueDate = node.SelectSingleNode("DueDate") != null ? node.SelectSingleNode("DueDate").InnerText : "";
MaxCiSJob.CompletedDate = node.SelectSingleNode("CompletedDate") != null ? node.SelectSingleNode("CompletedDate").InnerText : "";
MaxCiSJob.ClientId = node.SelectSingleNode("Client/ID").InnerText;
MaxCiSJob.ManagerId = node.SelectSingleNode("Manager/ID") != null ? node.SelectSingleNode("Manager/ID").InnerText : "";
MaxCiSJob.PartnerId = node.SelectSingleNode("Partner") != null ? node.SelectSingleNode("Partner").InnerText : "";
XmlNodeList Assigned = node.SelectNodes("Assigned/Staff");
foreach (XmlNode staffNode in Assigned)
{
MaxCiSJob.Staffs.Clear();
var staffId = staffNode.SelectSingleNode("ID").InnerText;
var staff = _db.Staffs.Find(staffId);
if (staff != null)
{
MaxCiSJob.Staffs.Add(staff);
}
}
}
_db.SaveChanges();
And you should change your domains this way in order not to get NullReferenceException:
public class Staff
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Mobile { get; set; }
public string Address { get; set; }
//Navigation
public virtual ICollection<Job> Jobs { get; set; } = new Collection<Job>();
}
public class Job
{
[Key]
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string State { get; set; }
public string ClientOrderNumber { get; set; }
public string StartDate { get; set; }
public string DueDate { get; set; }
public string CompletedDate { get; set; }
public string ClientId { get; set; }
public string ManagerId { get; set; }
public string PartnerId { get; set; }
//Navigation
public virtual ICollection<Staff> Staffs { get; set; } = new Collection<Staff>();
}

How to insert values into a table with optional relationship in ef?

I have those two entities, PatientRegistry and PatientAccount. The relationship between them is 1-0..1. I am trying to seed in my primary table PatientRegistry but I keep getting null errors for required fields in my optional table PatientAccount, How can I insert values in my primary table without the need to seed in my optional table as well?
Unhandled Exception: Microsoft.EntityFrameworkCore.DbUpdateException:
An error occurred while updating the entries. See the inner exception
for details. ---> System.Data.SqlClient.SqlException: Cannot insert
the value NULL into column 'Password', table
'ArtCoreDb.dbo.AspPatientsAccount'; column does not allow nulls.
UPDATE fails.
public class PatientRegistry {
[DatabaseGenerated (DatabaseGeneratedOption.Identity)]
[Display (Name = "Record Id")]
public long RecordId { get; set; }
[Key, DatabaseGenerated (DatabaseGeneratedOption.None)]
[Display (Name = "Patient File Number")]
public long PatientFileId { get; set; }
[Required, StringLength (50)]
[Display (Name = "First Name")]
public string FirstName { get; set; }
public virtual ICollection<PartnerRegistry> Partners { get; set; }
public virtual PatientAccount PatientAccount { get; set; }
}
public class PatientAccount {
[Key, DatabaseGenerated (DatabaseGeneratedOption.Identity)]
public long RecordId { get; set; }
[Required]
public string Password { get; set; }
[Required, StringLength (15)]
public string MobileNo { get; set; }
public bool IsConfirmedPhoneNumber { get; set; } = false;
public bool IsConfirmedEmailAddress { get; set; } = false;
public bool IsLocked { get; set; } = false;
public int? FailedAttempts { get; set; }
public DateTimeOffset? LastLoggedIn { get; set; }
public DateTimeOffset DateCreated { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
public long? PatientFileId { get; set; }
public virtual PatientRegistry PatientFile { get; set; }
}
And my fluent API,
protected override void OnModelCreating (ModelBuilder builder) {
base.OnModelCreating (builder);
builder.Entity<PatientRegistry> ()
.HasOne (a => a.PatientAccount)
.WithOne (b => b.PatientFile)
.HasForeignKey<PatientAccount> (c => c.PatientFileId)
.OnDelete (DeleteBehavior.Cascade);
}
And I seed,
if (!context.PatientsRegistry.Any ()) {
context.PatientsRegistry.AddRange (
new PatientRegistry {
PatientFileId = 1111,
FirstName = "John"
}
);
context.SaveChanges ();
}
works only if I add ,,
PatientAccount =
new PatientAccount {
PatientFileId = 1111,
CountryCodeId = context.Countries.Where (g => g.Name == "United States of America").SingleOrDefault ().Id,
AreaCode = 424,
Email = "aamaizar#gmail.com",
MobileNo = "3244990",
IsConfirmedEmailAddress = false,
IsConfirmedPhoneNumber = false,
IsLocked = false,
Password = "213123",
},
in reality, I want to be able to insert in PatientsRegistry table without the need to insert into PatientAccount
Using Add (or AddRange) marks all reachable entities in the graph in added state, I just have to added PatientAccount prop to my object during seeding
new PatientRegistry { PatientFileId = 1111, FirstName = "John", PatientAccount = {.......} }
Ref

Entity Framework: Is it possible to insert the id of a newly created record into another record while running Seed method

I'm having issues when attempting to use the id created on one record for multiple records.
My models look like this:
public class Student
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int StudentId { get; set; }
public int PersonId { get; set; }
public string SID { get; set; }
public int AccountId { get; set; }
public bool Active { get; set; }
[ForeignKey("PersonId")]
public virtual Person Person { get; set; }
[ForeignKey("AccountId")]
public virtual Account Account { get; set; }
}
public class Person
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MI { get; set; }
public int SSN { get; set; }
public int AddressId { get; set; }
public int RaceId { get; set; }
[ForeignKey("AddressId")]
public Address Addresss { get; set; }
}
public class Address
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int AddressId { get; set; }
public string StreetAddress { get; set; }
public string City { get; set; }
public string State { get; set; }
public int ZipCode { get; set; }
}
using the following to seed the database:
context.Students.AddOrUpdate(x => x.SID,
new WestCobb.Data.Student
{
SID = "99-B50-404324175",
EnrollmentDate = Convert.ToDateTime("01-30-2017"),
Active = true,
Person = new WestCobb.Data.Person
{
FirstName = "Brian",
LastName = "Folks",
AddressId = 4,
SSN = 404324175,
Addresss = new WestCobb.Data.Address // This address!
{
StreetAddress = "5076 Lake Charles Court",
City = "Chicago",
State = "Illinois",
ZipCode = 60208
}
},
Account = new WestCobb.Data.Account
{
AccountNumber = "M00000000000088",
AccountTypeId = 1,
Priority = 1,
Rate = 225.00m,
BillingCycleId = 1,
CreateDate = Convert.ToDateTime("01-30-2017"),
Active = true
}
},
// Manually set AddressId of this Person to AddressId of previous Person added
new WestCobb.Data.Student
{
SID = "99-A50-404527896",
EnrollmentDate = Convert.ToDateTime("01-30-2017"),
Active = true,
Person = new WestCobb.Data.Person
{
FirstName = "Arthur",
LastName = "Clue",
SSN = 404527896,
AddressId = context.Addresses.Last().AddressId // This seems not to work
},
Account = new WestCobb.Data.Account
{
AccountNumber = "W89322198433588",
AccountTypeId = 1,
Priority = 2,
Rate = 225.00m,
BillingCycleId = 1,
CreateDate = Convert.ToDateTime("01-30-2017"),
Active = true
}
}
);
and getting the following error:
LINQ to Entities does not recognize the method 'WestCobb.Data.Address Last[Address](System.Linq.IQueryable`1[WestCobb.Data.Address])' method, and this method cannot be translated into a store expression.
Is it possible to use the same "id" (AddressId) that was created from the insertion of the first Person's address in the Address of the second Person? I want to use the same Id for the AddressId of multiple Persons.
If you want to use the same Address entity to multiple Persons, why don't you create the Address first, then use it as many times as you want ?
var myAwesomeAddress = new WestCobb.Data.Address()
{
StreetAddress = "5076 Lake Charles Court",
City = "Chicago",
State = "Illinois",
ZipCode = 60208
};
// You should have a DbSet of your Addresses right ?
context.Addresses.AddOrUpdate(x => x.Id, // Use any discriminator
myAwesomeAddress
);
context.Students.AddOrUpdate(x => x.SID,
new WestCobb.Data.Student
{
SID = "99-B50-404324175",
EnrollmentDate = Convert.ToDateTime("01-30-2017"),
Active = true,
Person = new WestCobb.Data.Person
{
FirstName = "Brian",
LastName = "Folks",
AddressId = 4,
SSN = 404324175,
Addresss = myAwesomeAddress
}
},
new WestCobb.Data.Student
{
SID = "99-A50-404527896",
EnrollmentDate = Convert.ToDateTime("01-30-2017"),
Active = true,
Person = new WestCobb.Data.Person
{
FirstName = "Arthur",
LastName = "Clue",
SSN = 404527896,
Address = myAwesomeAddress // here
}
}
);

Entity Framework - DbContext SaveChanges()

Can someone tell me is it possible, and if it is how to avoid using two times _context.SaveChanges() in this code?
Message m = new Message
{
Title = message.Title,
Body = message.Body,
Date = DateTime.Now
};
_context.Messages.Add(m);
_context.SaveChanges();
UserMessage messageToUser = new UserMessage
{
MessageID = m.ID,
ProductID = message.ProductID,
SenderID = message.SenderID,
RecieverID = reciever.Id
};
_context.UserMessages.Add(messageToUser);
_context.SaveChanges();
This is how my Entities look like
public class UserMessage
{
public int ID { get; set; }
public string SenderID { get; set; }
public string RecieverID { get; set; }
public int? ProductID { get; set; }
public int MessageID { get; set; }
public User Sender { get; set; }
public User Reciever { get; set; }
public Product Product { get; set; }
public Message Message { get; set; }
}
public class Message
{
public int ID { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public DateTime Date { get; set; }
}
On your UserMessage class, you set the reference instead of the foreign key, as the foreign key is not known yet.
In your code, that would mean:
Message m = new Message
{
Title = message.Title,
Body = message.Body,
Date = DateTime.Now
};
_context.Messages.Add(m);
UserMessage messageToUser = new UserMessage
{
ProductID = message.ProductID,
SenderID = message.SenderID,
RecieverID = reciever.Id,
Message = m
};
_context.UserMessages.Add(messageToUser);
_context.SaveChanges();

model passed to dictionary is of type .Data.Entity.Infrastructure.DbQuery , but it requires a model of type 'System.Collections.Generic.IEnumerable

What I am trying to do is
UserRoles:
public class UserRolesController : Controller
{
private HMSEntities db = new HMSEntities();
//
// GET: /UserRoles/
public ActionResult Index()
{
User user = (User)Session["User"];
var usr = db.Users.Find(user.Id);
ViewBag.Id = usr.Id;
ViewBag.FirstName = usr.FirstName;
if (Session["User"] != null)
{
var role = db.Roles.Where(u => u.Id == user.RoleId);
}
return View(usr);
}
Index.cshtml
#model IEnumerable<HMS.Models.User>
#using HMS.Models;
In this project when a user logs in then the user can view their details and then perform crud operations on roles of that user, but I am getting an error:
The model item passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery1[HMS.Models.Role]', but
this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable1[HMS.Models.User]'.
My Models are:
Role.cs
public partial class Role
{
public Role()
{
this.Users = new HashSet<User>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
User.cs
public partial class User
{
public User()
{
this.Accesses = new HashSet<Access>();
this.Doctors = new HashSet<Doctor>();
this.Patients = new HashSet<Patient>();
this.Staffs = new HashSet<Staff>();
}
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Nullable<System.DateTime> DOB { get; set; }
public Nullable<int> Age { get; set; }
public Nullable<int> PhoneNo { get; set; }
public Nullable<int> LandlineNO { get; set; }
public Nullable<bool> Status { get; set; }
public string PermentAddress { get; set; }
public string TemproryAddress { get; set; }
public string BloodGroup { get; set; }
public string Gender { get; set; }
public string EducationFinal { get; set; }
public string Experience { get; set; }
public string EmailId { get; set; }
public byte[] Image { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public Nullable<int> RoleId { get; set; }
public virtual ICollection<Access> Accesses { get; set; }
public virtual ICollection<Doctor> Doctors { get; set; }
public virtual ICollection<Patient> Patients { get; set; }
public virtual Role Role { get; set; }
public virtual ICollection<Staff> Staffs { get; set; }
}
I am new to mvc and don't know what else to do. If any further code is required please do tell and please reply.
db.Roles.Where(u => u.Id == user.RoleId);
Returns a DBQuery:
You have to convert it to List or Enumerable.
ViewBag.role = db.Roles.Where(u => u.Id == user.RoleId).AsEnumerable();
return View(ViewBag.role);
OR if you use List:
ViewBag.role = db.Roles.Where(u => u.Id == user.RoleId).ToList();
And you don't need to put in ViewBag:
var roles = db.Roles.Where(u => u.Id == user.RoleId).AsEnumerable();
return View(roles);
And in your View Change the Model from User to Roles:
#model IEnumerable<HMS.Models.User>
To Roles
#model IEnumerable<HMS.Models.Roles>
EDIT:
You are returning a Enumerable of Roles on this LINE: if (usr != null) return View(ViewBag.role); Not a User.
If you want to return the User and the Roles, you have to include the Roles in the User Model.
Something Like this in controller:
var usr = db.Users.Find(user.Id);
usr.Roles = db.Roles.Where(u => u.Id == user.RoleId).ToList();
return View(usr);
Then in the View:
#model HMS.Models.User
#foreach(var role in Model.Roles){
<p>#role.RoleId</p>
}