Multiplicity constraint violated. DB first EF 4.1 - asp.net-mvc

I have the following model:
the i run the following to add a new user:
using (var context = new CamelotDB())
{
Console.WriteLine("Creating Test User");
DomainEntity userToAdd = new DomainEntity()
{
EntityName = "Test User",
EntityType = DomainEntity.eEntityType.User,
EntityCreationDate = DateTime.Now,
EntityLastUpdateDate = DateTime.Now,
EntityCreatorUserID = 0,
Creator = context.DomainEntities.Find(0),
EntityUpdaterUserID = 0,
Updater = context.DomainEntities.Find(0),
EntityParentID = null,
UserDetails = new User()
{
Username = "TestUser",
Password = "123",
Email = "TestUser#Test.org",
FirstName = "Test",
LastName = "User",
Phone = "123456789"
}
};
Console.WriteLine("Adding user to Database...");
userToAdd = context.DomainEntities.Add(userToAdd);
context.SaveChanges();
}
And I get the following error:
Multiplicity constraint violated. The role 'User' of the relationship 'CamelotShiftManagement.DAL.DomainEnttyFK1' has multiplicity 1 or 0..1.![enter image description here]

The problem was not the user entity referenced by the Domain Entity.
The problem is the self references for the creator and updater.
they are both not Nullable ... so i had to add an actual ID number to the properties and that required to place an actual User entity in the Navigation Properties of Creator and Updater.

Related

The conflict occurred in database "X", table "dbo.Y", column 'ld'

I'm trying to get a certain amount of animals that have the most comments once I try to delete one of them so I'm getting an error of:
SqlException: The DELETE statement conflicted with the REFERENCE constraint "FK__Comments__Animal__2EDAF651". The conflict occurred in database "PetShop", table "dbo.Comments", column 'AnimalId'. The statement has been terminated.
I want to make it possible that if I delete then you will move on to the next in line
My Controller for disply:
public async Task<IActionResult> Index()
{
var animal = _context.Animals.Include(c => c.Comments).OrderByDescending(c => c.Comments.Count).Take(2);
return View(await animal.ToListAsync());
}
My Controller for Delete:
public async Task<Animal> DeleteAnimal(int id)
{
var comment = await _context.Comments.FindAsync(id);
_context.Comments.Remove(comment!);
var animal = await _context.Animals.FindAsync(id);
_context.Animals.Remove(animal!);
await _context.SaveChangesAsync();
return animal!;
}
My Context:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Comment>(entity =>
{
entity.HasOne(d => d.Animal)
.WithMany(p => p.Comments)
.HasForeignKey(d => d.AnimalId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK__Comments__Animal__2EDAF651");
});
modelBuilder.Entity<Category>(entity =>
entity.HasData(
new { CategoryId = 1, Name = "Dogs" },
new { CategoryId = 2, Name = "Cats" },
new { CategoryId = 3, Name = "Birds" },
new { CategoryId = 4, Name = "Rabbits" },
new { CategoryId = 5, Name = "Hamsters" }
)
);
modelBuilder.Entity<Animal>(entity =>
{
entity.HasData(
new { AnimalId = 1, Name = "Shoko", BirthDate = DateTime.Now.AddYears(-1).AddMonths(-1).AddDays(-12), Description = "Friendly and loyal", CategoryId = 1, PhotoUrl = "ShokoDog.jpg" },
new { AnimalId = 2, Name = "Bamba", BirthDate = DateTime.Now.AddYears(-2).AddMonths(-2).AddDays(-3), Description = "Furry and neutered", CategoryId = 2, PhotoUrl = "BambaCat.jpg" },
new { AnimalId = 3, Name = "Regev", BirthDate = DateTime.Now.AddYears(-1).AddMonths(-3).AddDays(-3), Description = "Speak", CategoryId = 3, PhotoUrl = "RegevBird.jpg" },
new { AnimalId = 4, Name = "Humi", BirthDate = DateTime.Now.AddYears(-3).AddMonths(-4).AddDays(-7), Description = "Cute and furry", CategoryId = 4, PhotoUrl = "HumiRabbit.jpg" },
new { AnimalId = 5, Name = "Tommy", BirthDate = DateTime.Now.AddYears(-1).AddMonths(-7).AddDays(-9), Description = "Love to play in the facilities", CategoryId = 5, PhotoUrl = "TommyHamster.jpg" });
});
OnModelCreatingPartial(modelBuilder);
}
You want to remove a parent Animal and related child Comments
To expand on Karlis' suggestions:
You have models and context as posted in the question (it's a bit problematic because you say to EF to set null, but the code and DB won't accept null) but you can do:
var a = context.Animals.Include(a => a.Comments).Find(id):
context.Comments.RemoveRange(a.Comments);
context.Animals.Remove(a);
context.SaveChanges();
This explicitly removes the comments then the animal
Change the context to use .OnDelete(DeleteBehavior.ClientCascade) then you can do:
var a = context.Animals.Include(a => a.Comments).Find(id):
context.Animals.Remove(a);
context.SaveChanges();
This causes EF to implicitly remove the comments it knows about when you tell it explicitly to remove the animal
Change the DB's foreign key to do an ON DELETE CASCADE, and change .OnDelete(DeleteBehavior.Cascade) then you can skip downloading the Comments (no include):
var a = context.Animals.Find(id):
context.Animals.Remove(a);
context.SaveChanges();
This causes the DB to remove the comments (EF doesn't know about them) when EF instructs to delete the animal
Broadly speaking, these are in order of "how bad of a mistake could you make" from "not very" to "quite a lot"
The error message reads that you are deleting Animal, which has comments associated. You should do one of the following:
Remove comments associated with a particular Animal before deleting the Animal.
Check EF configuration for cascade on delete
Alter FK to have cascade on delete (it depends on whether you are using a database-first or code-first approach)
I would go for the first approach because cascade on delete may be dangerous and silently remove unintentionally referenced data.

Seed Method Doesn't Populate Tables

The database is create successfully as well as the tables. However, whether I put the seed code in the configuration file or as a initializer. The tables are never populated with data.
Things I have tried:
1. I have been viewed several posts on stackoverflow comparing my code with solutions to no avail.
2. I changed DropCreateDatabaseIfModelChanges to DropCreateDatabaseAlways, still the same.
3. I have verified all required fields have a value
public class BankAccountInitializer : DropCreateDatabaseAlways<BankAccountContext>
{
protected override void Seed(BankAccountContext context)
{
var bank1 = new Bank(1) { BankName = "Huntington", BankAccounts = new List<BankAccount>() };
context.Banks.Add(bank1);
context.BankAccounts.Add
(
new CheckingAccount(1)
{
BankId = 1,
AccountBalance = 25.00m,
BankAccountName = "Checking Account 1",
DateAdded = DateTime.Now,
RoutingNumber = 00000887,
Owner = "Checking Account Owner 1",
Bank = bank1
}
);
context.BankAccounts.Add
(
new IndividualInvestment(2)
{
BankId = 1,
AccountBalance = 10.00m,
BankAccountName = "Individual Investment 1",
DateAdded = DateTime.Now,
RoutingNumber = 00000887,
Owner = "Individual Investment Owner 1",
Bank = bank1
}
);
context.BankAccounts.Add(
new CorporateInvestment(3)
{
BankId = 1,
AccountBalance = 98.00m,
BankAccountName = "Corporate Investment 1",
DateAdded = DateTime.Now,
RoutingNumber = 00000887,
Owner = "Corporate Investment Owner 1",
Bank = bank1
}
);
base.Seed(context);
}
}
}

How To Filter The Data sent To The View According to the user login

This Is My Code
[Authorize(Roles = "Supplier")]
public ActionResult Orders()
{
if (!String.IsNullOrEmpty(TempData["error"] as string))
ViewBag.Error = TempData["error"] as string;
TempData.Clear();
if (User.IsInRole("Admin"))//when the user logs in as the admin
{
var orders = _uow.orderRepo.GetAll().ToList();
List<Models.Admin.OrderGridModel> model = null;
model = (from c in orders
select new Models.Admin.OrderGridModel()
{
OrderNumber = c.OrderNumber,
Date = c.Date,
Id = c.Id,
FullName = c.Person.FirstName + " " + c.Person.LastName,
PhoneNr = c.Person.Tel,
Email = c.Person.Email,
Price = BLL.PriceFormatter.FormatPrice(c.Price, c.Currency),
IsPaid = c.Zaplaceno,
Activities = (from a in c.OrderActivities
select new Models.Admin.OrderGridActivityModel()
{
Id = a.Id,
Time = a.Time,
Name = a.Activity.Name,
Date = a.Date,
Status = a.Status,
Supplier = a.Activity.Supplier != null ? a.Activity.Supplier.Name : "",
BookingRefNr = a.SupplierRefNr,
Hotel = c.Hotelname,
Price = BLL.PriceFormatter.FormatPrice(a.Price, a.Order.Currency),
PriceTypes = BLL.PriceFormatter.GetPriceTypesToString(a.OrderPrices),
voucher_ext = a.VoucherFileExtension,
voucher_name = a.VoucherFileName,
voucher_type = a.VoucherFileContentype,
}).ToList()
}).ToList();
return View(model);
}
if (User.IsInRole("Supplier"))// when the user logs in as the supplier
{
//code for filtering according to the supplier
}
return View();
}
I am getting the orders from the database but i want it to be filtered when the supplier logs in only those records can will be returned in which the supplier name is according to the login
In your repository, you have this
_uow.orderRepo.GetAll();
Create another one where you filter by supplier id
public IList<Order> GetSupplier(string id)
{
return context.Orders.Where(o => o.User.Id = id).ToList();
}
and then you can do this:
_uow.orderRepo.GetSupplier(User.Identity.GetUserId());
Where User.Identity.GetUserId() is the logged in user.

Below is my code of create action which is not working And I have checked my database edmx file and all but still it's not working

I am creating Employee registration form. I have stored UserName ,Password and Role field in Login table and address, phon no. and as shown below details in employee table. As per my knowledge I have tried all efforts but this create method is not working... Please help me
public ActionResult Create(EmployeeViewModel model)
{
if (ModelState.IsValid)
{
var search = db.Logins.FirstOrDefault(x => x.UserEmail == model.UserEmail);
if (search != null)
{
ViewBag.Message = "Email you've enter is used by someone else. Reenter please";
}
else
{
Login login = new Login
{
UserEmail = model.UserEmail,
UserPass = (model.UserPass),
RoleID = 2,
Created = DateTime.Now,
IsVerified = true
};
db.Logins.Add(login);
db.SaveChanges();
DivineDemo.Employee emp = new DivineDemo.Employee
{
EmpID = login.UserID,
EmpName = model.EmpName,
Address = model.Address,
CityID = model.CityID,
PhoneNo = model.PhonNo,
Gender = model.Gender
//JoinDate = DateTime.Now
};
db.Employees.Add(emp);
db.SaveChanges();
ViewBag.Message = "Employee added successfully";
ModelState.Clear();
}
}
return View(model);
}
I found my ans by examining the locals from debug. Modelstate.isvalid method was turned to false thatsway values are not inserted in db

Why does UserManager.FindById() return null if I do not relog?

I'm trying to find the user associated with the currently logged on user:
public ActionResult Root(string path)
{
var id = User.Identity.GetUserId(); //This works
var currentUser = manager.FindById(id); //This returns null
return View(db.Folders.ToList()
.Where(folder => folder.User.Id == currentUser.Id)
.Where(folder => folder.Path == path));
}
This only works if I do not use the indicated part in my seed method. If I do execute this part, manager.FindById() returns null.
protected override void Seed(ApplicationDbContext context)
{
if (context == null)
{
throw new ArgumentNullException("context", "Context must not be null.");
}
const string UserName = "admin#tad.com";
const string RoleName = "Admin";
var userRole = new IdentityRole { Name = RoleName, Id = Guid.NewGuid().ToString() };
context.Roles.Add(userRole);
var hasher = new PasswordHasher();
var user = new ApplicationUser
{
UserName = UserName,
PasswordHash = hasher.HashPassword("123456"),
Email = "admin#tad.com",
EmailConfirmed = true,
SecurityStamp = Guid.NewGuid().ToString()
};
user.Roles.Add(new IdentityUserRole { RoleId = userRole.Id, UserId = user.Id });
context.Users.Add(user);
//If I leave this part out, there are no issues.
new List<Folder>
{
new Folder{Name = "Test", Path = "", User = user},
new Folder{Name = "Bla", Path = "Test", User = user},
new Folder{Name = "Lala", Path = "Test/Bla", User = user}
}.ForEach(f => context.Folders.Add(f));
context.SaveChanges();
base.Seed(context);
}
EDIT: Starting to narrow it down. If I relog my user, everything works just fine. The active user during testing remains logged in from the previous debugging session.
I see the problem:
The active user during testing remains logged in from the previous debugging session.
Authentication cookie contains the Guid for userId from the previous session. And if you re-create users every time, guid for userId is getting changed in the database and does not match for whatever Id is stored in the cookie. So either don't re-create users on every debug session, or kill your cookies on every debug.

Resources