EF Core : what can I do if I get this error in the project I am working on:
MySqlException: Duplicate entry '2' for key 'customers.IX_Customers_UserID'
UserID causes this error when it is present - I do not understand exactly what the error is, please help
public class Context : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Address> Addresses { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//optionsBuilder.UseSqlite("Data Source = Shop.db");
//optionsBuilder.UseSqlServer(#"Data Source = (localdb)\v11.0; Initial Catalog=ShopDb; Integrated Security = SSPI;");
optionsBuilder.UseMySql(#"server=localhost;port=3306;database=ShopDb1;user=root;password=admin123;");
}
public Context()
{
Database.EnsureCreated();
}
}
public class User
{
public int ID { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public Customer Customer { get; set; }
public List<Address> Addresses { get; set; }
}
public class Customer
{
public int ID { get; set; }
public int IdentifyNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public User User { get; set; }
public int UserID { get; set; }
}
public class Supplier
{
public int ID { get; set; }
public string Name { get; set; }
public string TaxNumber { get; set; }
}
public class Address
{
public int ID { get; set; }
public string FullName { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public User User { get; set; }
public int UserID { get; set; }
}
public class Product
{
public int ProductID { get; set; }
[MaxLength(100)]
[Required]
public string Name { get; set; }
public decimal Price { get; set; }
public int CategoryID { get; set; }
}
public class Category
{
public int CategoryID { get; set; }
[MaxLength(100)]
[Required]
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var db = new Context())
{
var customer = new Customer()
{
IdentifyNumber = 123,
FirstName = "Remzi",
LastName = "Balakishiyev",
User = db.Users.FirstOrDefault(x => x.ID == 2)
};
db.Customers.Add(customer);
db.SaveChanges();
}
Console.ReadLine();
}
static void InsertUsers()
{
var users = new List<User> {
new User() { UserName ="Remzi",Email = "remzi.balakisiyev#gmail.com"},
new User() { UserName ="Xezri",Email = "xezri.balakisiyev#gmail.com"},
new User() { UserName ="Nurane",Email = "nurane.tarverdiyeva#gmail.com"}
};
using (var db = new Context())
{
db.Users.AddRange(users);
db.SaveChanges();
}
}
static void InsertAddresses()
{
var addresses = new List<Address> {
new Address() { FullName = "Remzi Balakisiyev", Title = "Ev addressi", Body = "Masalli", UserID = 1 },
new Address() { FullName = "Remzi Balakisiyev", Title = "Ish addressi", Body = "Baki", UserID = 1 },
new Address() { FullName = "Xezri Balakisiyev", Title = "Ev addressi", Body = "Masalli", UserID = 2 },
new Address() { FullName = "Nurane Tarverdiyeva", Title = "Ev addressi", Body = "Naxcivvan", UserID = 3},
new Address() { FullName = "Rena Heyderova", Title = "Ev addressi", Body = "Xachmaz", UserID = 2 },
new Address() { FullName = "Memmed Bedelov", Title = "Ev addressi", Body = "Sumqayit", UserID = 1 }
};
using (var db = new Context())
{
db.Addresses.AddRange(addresses);
db.SaveChanges();
Console.WriteLine("Ishledi");
}
}
}
Your problem most probably is running on these lines of code:
var users = new List<User> {
new User() { UserName ="Remzi",Email = "remzi.balakisiyev#gmail.com"},
new User() { UserName ="Xezri",Email = "xezri.balakisiyev#gmail.com"},
new User() { UserName ="Nurane",Email = "nurane.tarverdiyeva#gmail.com"}
};
using (var db = new Context())
{
db.Users.AddRange(users);
db.SaveChanges(); // ERROR happening here, when trying to insert Users
}
The error is happening because you have put a unique PRIMARY Key constraint over the UserId column.
Try adding the following attribute over the ID, to fix the issue:
public class User
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
...
}
Another note, I think the UserId property redundant in your Customer class.
Please also check that if your Userā¶Customer relations are defined as one-to-many, then in your Customer class you have to define a collection of Users but not a single User:
public class Customer
{
...
public ICollection<User> Users { get; set; }
}
For more information check here.
Related
When I try to create a new dialog and insert it in the database with 2 foreign relations entities Account and Customer who are in the database with both CustomerID 1 and AccountID 1 I get this error, I think it tries to also insert a new customer and a new account but thats not what I want....
My code looks like this:
public Dialog CloseAndSaveDialog(Dialog dialog)
{
try
{
DialogDTOC converter = new DialogDTOC();
AccountContainer accountContainer = new AccountContainer(_dbContext);
DialogDTO dialogDto = converter.ModelToDto(dialog);
dialogDto.Customer = new CustomerDTO() { CustomerID = 1 };
dialogDto.Account = new AccountDTO() { AccountID = 1 };
dialogDto.CreationTime = DateTime.Now;
dialogDto.Status = "Closed";
_dbContext.dialogs.Add(dialogDto);
_dbContext.SaveChanges();
return converter.DtoToModel(dialogDto);
}
catch (Exception ex)
{
return null;
}
}
[Table(name: "Dialogs")]
public class DialogDTO
{
[Key]
public int DialogID { get; set; }
[ForeignKey("AccountID")]
public virtual AccountDTO Account { get; set; }
[ForeignKey("CustomerID")]
public virtual CustomerDTO Customer { get; set; }
[Column(TypeName = "varchar(500)")]
public string Status { get; set; } = string.Empty;
[Column(TypeName = "datetime")]
public DateTime CreationTime { get; set; }
}
[Table(name: "Customers")]
public class CustomerDTO
{
[Key]
public int CustomerID { get; set; }
}
[Table(name: "Accounts")]
public class AccountDTO
{
[Key]
public int AccountID { get; set; }
[Column(TypeName = "varchar(500)")]
public string Username { get; set; } = string.Empty;
[ForeignKey("CompanyID")]
public virtual CompanyDTO Company { get; set; } = new CompanyDTO();
[Column(TypeName = "varchar(500)")]
public string Email { get; set; } = string.Empty;
[Column(TypeName = "varchar(500)")]
public string Password { get; set; } = string.Empty;
}
I'm trying to build an application in Mvc with Individual User Accounts, and I'm trying to connect the automatically generated database with my own context.
The problem I have when I trying to create a view of my Create method I get this errormessage:
There was an error running the selected code generator: 'Unable to
retrieve metadata for 'Projekt_Dejtingsida.Models.Messages' is not
valid. The navigation property 'ApplicationUser' was not found on the
dependent type 'Projekt_Dejtsida.Models.Messages'. The Name value
should be a valid navigation property name.
Please help a beginner out!
Here are the models I'm using:
I have already tried the protected override void OnModelCreating(DbModelBuilder modelBuilder) method, but it didn't work...
public class Messages {
[Key, ForeignKey("ApplicationUser")]
public string Id { get; set; }
[Key]
public int MessageId { get; set; }
public virtual ApplicationUser Sender { get; set; }
public virtual ApplicationUser Receiver { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "You can't send a message without a content")]
[StringLength(300, MinimumLength = 3, ErrorMessage = "Your message should be between 3 and 300 characters")]
public string MessageContent { get; set; }
}
public class FriendRequests {
public string UserId { get; set; }
[Key]
public int RequestId { get; set; }
public virtual ApplicationUser RequestTo { get; set; }
public virtual ApplicationUser RequestFrom { get; set; }
public bool Confirmed { get; set; }
}
public class Profile {
[Key]
public string UserId { get; set; }
public byte[] ProfilePicture { get; set; }
public string Firstname { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public string About { get; set; }
public virtual ICollection<Messages> MyMessages { get; set; }
}
Here is the DbContext:
public class DatesiteContext : DbContext {
public DatesiteContext() : base() { }
public DbSet<FriendRequests> Requests { get; set; }
public DbSet<Messages> Messages { get; set; }
public DbSet<Profile> Profiles { get; set; }
}
Here is the MessageController
[Authorize]
public class MessageController : Controller
{
// GET: Message
public ActionResult Index()
{
var db = new DatesiteContext();
var userId = User.Identity.GetUserId();
var msgs = db.Messages.FirstOrDefault(m => m.Id == userId);
return View(new MessageViewModel {
Sender = msgs.Sender,
Receiver = msgs.Receiver,
MessageContent = msgs.MessageContent
});
}
public ActionResult Create(MessageViewModel model) {
DatesiteContext db = new DatesiteContext();
var userId = User.Identity.GetUserId();
var msgs = db.Messages.FirstOrDefault(m => m.Id == userId);
if (msgs == null) {
db.Messages.Add(new Messages {
Id = userId,
Sender = msgs.Sender,
Receiver = msgs.Receiver,
MessageContent = msgs.MessageContent
});
} else {
msgs.Sender = model.Sender;
msgs.Receiver = model.Receiver;
msgs.MessageContent = model.MessageContent;
}
db.SaveChanges();
return RedirectToAction("Index", "Profile");
}
}
when my code is executing then i am getting this error.
CurrentValues cannot be used for entities in the Deleted state
here is my code
private void button3_Click(object sender, EventArgs e)
{
Addresses CurrentAddress = null;
Contacts CurrentContacts = null;
using (var db = new TestDBContext())
{
var existingCustomer = db.Customer
.Include(a => a.Addresses.Select(x => x.Contacts))
.FirstOrDefault(p => p.CustomerID == 5);
existingCustomer.FirstName = "Test Customer122";
// selecting address
foreach (var existingAddress in existingCustomer.Addresses.Where(a => a.AddressID == 5).ToList())
{
CurrentAddress = existingAddress;
//if (existingCustomer.Addresses.Any(c => c.AddressID == existingAddress.AddressID))
db.Addresses.Remove(existingAddress);
}
Addresses oAdrModel = new Addresses();
if (CurrentAddress != null)
{
oAdrModel.Address1 = "test add2";
oAdrModel.Address2 = "test add2";
oAdrModel.SerialNo = 3;
oAdrModel.IsDefault = true;
oAdrModel.CustomerID = existingCustomer.CustomerID;
db.Entry(CurrentAddress).CurrentValues.SetValues(oAdrModel);
}
else
{
db.Addresses.Add(oAdrModel);
}
// selecting contacts
foreach (var existingContacts in existingCustomer.Addresses.SelectMany(a => a.Contacts.Where(cc=> cc.ContactID==5)))
{
CurrentContacts = existingContacts;
db.Contacts.Remove(CurrentContacts);
}
Contacts ContactModel = new Contacts();
if (CurrentContacts != null)
{
ContactModel.Phone = "1111111-33";
ContactModel.Fax = "1-1111111";
ContactModel.SerialNo = 4;
ContactModel.IsDefault = true;
ContactModel.AddressID = CurrentAddress.AddressID;
db.Entry(CurrentAddress).CurrentValues.SetValues(oAdrModel);
}
else
{
db.Contacts.Add(ContactModel);
}
db.SaveChanges();
}
}
i am removing data and updateing the data the above way. i got the concept from this SO link https://stackoverflow.com/a/27177623/728750
this below lines of code throwing the error
foreach (var existingAddress in existingCustomer.Addresses.Where(a => a.AddressID == 5).ToList())
{
CurrentAddress = existingAddress;
//if (existingCustomer.Addresses.Any(c => c.AddressID == existingAddress.AddressID))
db.Addresses.Remove(existingAddress);
}
what kind of mistake i have done here. please rectify me.
Classes relation
public class CustomerBase
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string Address1 { get; set; }
[NotMapped]
public string Address2 { get; set; }
[NotMapped]
public string Phone { get; set; }
[NotMapped]
public string Fax { get; set; }
}
public class Customer : CustomerBase
{
public virtual List<Addresses> Addresses { get; set; }
}
public class Addresses
{
[Key]
public int AddressID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public bool IsDefault { get; set; }
public int SerialNo { get; set; }
public virtual List<Contacts> Contacts { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; }
}
public class Contacts
{
[Key]
public int ContactID { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public bool IsDefault { get; set; }
public int SerialNo { get; set; }
public int AddressID { get; set; }
public virtual Addresses Customer { get; set; }
}
thanks
I'm having the strangest problem and I know it's because I'm missing something obvious because this set up works fine when I save data and even pull it down.
My app is set up like so ....
WebUI depends on Business Layer .. Business Layer depends on Data Layer (which is where I'm actually pulling the data). The Business Layer does all the "work".
This is where everything dies (Null Exception, Object Reference not set) as soon as I assign something to userInfo.userData.avatarFilepath (which is not null).
namespace pgl.businesslayer
{
public class userCtx
{
private pgl.datalayer.Concrete.EFDbContext context = new pgl.datalayer.Concrete.EFDbContext();
private pgl.datalayer.Concrete.EFUserContext userContext = new pgl.datalayer.Concrete.EFUserContext();
private pgl.datalayer.Concrete.EFDbCompany companyContext = new pgl.datalayer.Concrete.EFDbCompany();
public ViewModels.UserInfo getUserById(int userId)
{
ViewModels.UserInfo userInfo = new ViewModels.UserInfo();
pgl.datalayer.Dtos.pglUserDTO userDL = userContext.getUserByUserId(userId);
userInfo.userData.avatarFilepath = userDL.avatarFilepath;
userInfo.userData.createdBy = userDL.createdBy;
userInfo.userData.createdDate = userDL.createdDate;
userInfo.userData.email = userDL.email;
userInfo.userData.firstName = userDL.firstName;
userInfo.userData.lastName = userDL.lastName;
etc...
}
ViewModels.UserInfo looks like this...
namespace pgl.businesslayer.ViewModels
{
public class UserInfo
{
// user info
public pgl.businesslayer.Dto.pglUser userData { get; set; }
// salon info
public List<pglSalon> salonsData { get; set; }
// company info
public pglCompany companyData { get; set; }
}
pglUser in the business layer looks like this and is just a POCO
namespace pgl.businesslayer.Dto
{
public class pglUser
{
public int userId { get; set; }
public int companyId { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string email { get; set; }
public string username { get; set; }
public byte[] passwordSalt { get; set; }
public byte[] passwordKey { get; set; }
public DateTime createdDate { get; set; }
public int createdBy { get; set; }
public bool passwordResetRequired { get; set; }
public string passwordHash { get; set; }
public string tempPassword { get; set; }
public string userType { get; set; }
public string avatarFilepath { get; set; }
public string timeZone { get; set; }
}
}
And in userContext this is how I am pulling the user data...
public pgl.datalayer.Dtos.pglUserDTO getUserByUserId(int userId)
{
var getUser = (from u in context.pglUser
select new pgl.datalayer.Dtos.pglUserDTO
{
username = u.username,
companyId = u.companyId,
userId = u.userId,
userType = u.userType,
firstName = u.firstName,
lastName = u.lastName,
email = u.email,
createdDate = u.createdDate,
createdBy = u.createdBy,
passwordResetRequired = u.passwordResetRequired,
tempPassword = u.tempPassword,
avatarFilepath = u.avatarFilepath,
timeZone = u.timeZone
}).Where(u => u.userId == userId).FirstOrDefault();
return getUser;
}
pgl.datalayer.Dtos.pglUserDTO looks like this...
namespace pgl.datalayer.Dtos
{
public class pglUserDTO
{
public int userId { get; set; }
public int companyId { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string email { get; set; }
public string username { get; set; }
public byte[] passwordSalt { get; set; }
public byte[] passwordKey { get; set; }
public DateTime createdDate { get; set; }
public int createdBy { get; set; }
public bool passwordResetRequired { get; set; }
public string passwordHash { get; set; }
public string tempPassword { get; set; }
public string userType { get; set; }
public string avatarFilepath { get; set; }
public string timeZone { get; set; }
}
}
Even if I assign userInfo.userData.avatarFilepath = "WHATUP!!!" it throws the same error. This has got to be something stupid and simple. I can save data with no problem and when I debug I can see that it is actually pulling the correct user ID and it's associated data. It's just that pgl.businesslayer.ViewModels.UserInfo seems to be un-instantiated. I'm at a loss. I can provide more info... and keep in mind I'm kind of at my wits end so I tried doing weird things like adding (probably) unnecessary DTOs. Any ideas?
You don't appear to be creating the userData object anywhere. When you create a new instance of UserInfo, or in its constructor, try adding:
userData = new pgl.businesslayer.Dto.pglUser();
Or alternatively:
ViewModels.UserInfo userInfo = new ViewModels.UserInfo();
pgl.datalayer.Dtos.pglUserDTO userDL = userContext.getUserByUserId(userId);
userInfo.userData = new pgl.businesslayer.Dto.pglUser {
avatarFilepath = userDL.avatarFilepath,
createdBy = userDL.createdBy,
createdDate = userDL.createdDate,
email = userDL.email,
firstName = userDL.firstName,
lastName = userDL.lastName
};
If you always want to initialise UserInfo with an empty userData member, you could include the creation within the constructor:
namespace pgl.businesslayer.ViewModels
{
public class UserInfo
{
// Default constructor
public UserInfo()
{
userData = new pgl.businesslayer.Dto.pglUser();
}
// user info
public pgl.businesslayer.Dto.pglUser userData { get; set; }
// salon info
public List<pglSalon> salonsData { get; set; }
// company info
public pglCompany companyData { get; set; }
}
}
I have a function:
public void Add(User user)
{
var id = WebSecurity.CurrentUserId;
//add id to FK CUserID
context.User.Add(user);
}
I'm adding user data to database. How to add id value to CUserID?
public class User
{
[key]
public int UserID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string E-mail { get; set; }
public UserProfile CUserID { get; set; }
}
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int CUserId { get; set; }
public string UserName { get; set; }
}
EDIT:
If I try do:
user.CUserId = id;
I get an error:
Cannot implicitly convert type 'int' to 'Project.Models.UserProfile'
Change the User class:
public class User
{
[key]
int UserID { get; set; }
string Name { get; set; }
string Surname { get; set; }
string E-mail { get; set; }
[ForeignKey("UserProfile)]
int CUserID { get; set; }
virtual UserProfile UserProfile { get; set; ]
}
Now you can set the ID value and entity framework will get the matching UserProfile when you save changes.
Going on what you've described in your question, try this:
public void Add(User user)
{
using (var context = new MyDbContext())
{
var currentUser = context.UserProfile.Single(
u => u.UserName == System.Web.HttpContext.Current.User.Identity.Name);
var newUser = new User();
newUser.Name = user.Name;
newUser.Surname = user.Surname;
newUser.Email = user.Email;
newUser.CUserID = currentUser.CUserId;
context.User.Add(newUser);
context.SaveChanges();
}
}