DbUpdateException was Unhandled by user code in asp.net MVC - asp.net

I am working with chat server like Jobbr.net. when i close group chat tab then i am getting DbUpdateException was Unhandled by user code
Code:
public void CommitChanges()
{
_db.SaveChanges();
}
Click here to see screenshot

Looks like you got a problem with your data model or the data you want to persist. I guess some required field or foreign key is not set when you try to save the entity.
Try catching and logging the System.Data.Entity.Infrastructure.DbUpdateException. It should tell you which entity causes the problem. Here is some logging code that we use:
using NLog;
private static Logger Logger = LogManager.GetCurrentClassLogger();
try {
_db.SaveChanges();
}
catch (System.Data.Entity.Infrastructure.DbUpdateException upEx) {
if (upEx.Entries != null && upEx.Entries.Any()) {
Logger.Debug("DbUpdateException contained '{0}' entries:", upEx.Entries.Count());
// get info about the Entity that produced the error
foreach (var dbEntityEntry in upEx.Entries) {
if (dbEntityEntry.Entity != null) {
var entityType = dbEntityEntry.Entity.GetType();
try {
var id = entityType.GetProperty("Id").GetValue(dbEntityEntry.Entity, null);
Logger.Debug("DbUpdateException contains DbEntityEntry - Type: '{0}', Id: '{1}', State: '{2}'", entityType.Name, id, dbEntityEntry.State.ToString("G"));
} catch (Exception) {
Logger.Debug("DbUpdateException contains DbEntityEntry - Type '{0}', Id: unknown, State: '{2}'", entityType.Name, dbEntityEntry.State.ToString("G"));
}
}
}
}
}

Related

Old ASP.NET code works on one computer, not on another?

So in my global.asax, I've got the following code:
Inventory.BusinessTier bt = new Inventory.BusinessTier();
string UserLogin = bt.ExtractLogin (Request.ServerVariables ["AUTH_USER"]);
Inventory.User myUser = new Inventory.User (UserLogin);
Session ["User"] = myUser;
It works just fine on one development PC, but using the same version of Visual Studio, it craps out on the third line with this error:
System.TypeInitializationException: 'The type initializer for
'Inventory.DataTier' threw an exception.'
Inner Exception
NullReferenceException: Object reference not set to an instance of an
object.
Other than a line adding impersonation in my web.config (it has to be there now), I haven't changed a single thing. Is there a way to get more info on this? I can't even trace it, because if I put a debug line in the User object constructor, it never hits it. I'm at a bit of a loss. Would appreciate any advice.
EDIT to answer questions below:
InventoryUser is a very simple user object that reads the current from the database and stores some basic user info in properties, such as UserID, Role, RoleID, and IsAdmin.
The DataTier class is a class that interacts with the database. It is used in multiple projects, so I'm quite sure it's not the problem. I tried to paste in the code anyway, but it exceeded the limit for a post.
I'm reasonably sure the problem is related to the user class. It's short, so I can paste it in here:
using System;
using System.Data;
// This is the user business object. It contains information pertaining to the current user of the application. Notably, it
// contains the department ID, which determines what inventory items the user will see when using the application. Only
// specified employees with admin access can see all items for all departments, and that is determined by a specific department ID.
namespace Inventory {
public class User {
private Guid _UserID;
private Guid _RoleID;
private Guid _UserDepartmentID;
private string _UserRole = "";
private string _UserName = "";
private bool _IsAuthorizedUser = false;
private bool _IsAdmin = false;
// Attribute declarations
public Guid UserID {
get {
return _UserID;
}
set {
_UserID = value;
}
}
public string UserRole {
get {
return _UserRole;
}
set {
_UserRole = value;
}
}
public Guid RoleID {
get {
return _RoleID;
}
set {
_RoleID = value;
}
}
public string UserName {
get {
return _UserName;
}
set {
_UserName = value;
}
}
public Guid UserDepartmentID {
get {
return _UserDepartmentID;
}
set {
_UserDepartmentID = value;
}
}
public bool IsAdmin {
get {
return _IsAdmin;
}
set {
_IsAdmin = value;
}
}
public bool IsAuthorizedUser {
get {
return _IsAuthorizedUser;
}
set {
_IsAuthorizedUser = value;
}
}
// -----------------
// - Constructor -
// -----------------
public User (string UserLogin) {
string ShortUserLogin = ExtractLogin (UserLogin);
GetUser (ShortUserLogin);
}
// ------------------
// - ExtractLogin -
// ------------------
public string ExtractLogin (string Login) {
// The domain and "\" symbol must be removed from the string, leaving only the user name.
int pos = Login.IndexOf (#"\");
return Login.Substring (pos + 1, Login.Length - pos - 1);
}
// -------------
// - GetUser -
// -------------
// This method is called to fill the user object based on the user's login. It ultimately gets authorized user data
// from the user table.
public void GetUser (string UserName) {
DataTier dt1 = new DataTier();
DataTable dt = dt1.GetUserInfo (UserName);
int RecordCount = dt.Rows.Count;
switch (RecordCount) {
case 1: // There is one user name match, as there should be. This is the likely situation.
DataRow dr = dt.Rows[0];
UserID = (Guid)dr ["UserID"];
UserRole = (string)dr ["UserRole"];
RoleID = (Guid)dr ["RoleID"];
this.UserName = UserName;
UserDepartmentID = (Guid)dr ["DepartmentID"];
IsAdmin = (bool)dr ["IsAdmin"];
IsAuthorizedUser = true;
break;
case 0: // There are no user name matches (unauthorized use).
IsAdmin = false;
IsAuthorizedUser = false;
break;
default: // There are multiple user name matches (problem!).
IsAdmin = false;
IsAuthorizedUser = false;
break;
}
}
}
}

Error with EF when trying to save changes

I have an angular 8 app with .net core web api 2.1 and MS SQL SERVER.
I have login and logout implementation for users.
After the user logins, he can add or delete programming langugages.
When I perform a delete operation, I get the error
database operation expected to affect 1 row(s) but actually effected
5 rows
But the code works properly for finding that particular user and the ID of the programming language that he wants to delete.
Here is the image from the table: https://imgur.com/a/taZtJ7d
As you can see there are no duplicates.
I think it is something about Concurrency Conflicts. That's why I added a try-catch block with DbUpdateConcurrencyException.
It works sometimes and sometimes not.
Here, you can find the definiton for the table https://imgur.com/a/YMCYkNy
When I try the following method to delete Users from MS SQL, it works as it should:
public async Task<IActionResult> DeleteProgrammingLanguage(string userId, int plId)
{
UserPL ps = new UserPL();
try
{
ps = await _context.PlUsers.Where(x => x.UserId == userId && x.ProgrammingLanguageId == plId).SingleAsync();
_context.PlUsers.Remove(ps);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
throw ex;
}
return Ok(ps);
}
I solved my problem with this solution.
public IActionResult DeleteProgrammingLanguage(string userId, int plId)
{
using (_context)
{
// Fetch a person from database and change phone number
var ps = _context.PlUsers.FirstOrDefault(x => x.UserId == userId && x.ProgrammingLanguageId == plId);
// Change the person's name in the database to simulate a concurrency conflict
_context.PlUsers.Remove(ps);
var saved = false;
while (!saved)
{
try
{
// Attempt to save changes to the database
_context.SaveChanges();
saved = true;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is UserPL)
{
var proposedValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();
foreach (var property in proposedValues.Properties)
{
var proposedValue = proposedValues[property];
var databaseValue = databaseValues[property];
// TODO: decide which value should be written to database
// proposedValues[property] = <value to be saved>;
}
// Refresh original values to bypass next concurrency check
entry.OriginalValues.SetValues(databaseValues);
}
else
{
throw new NotSupportedException(
"Don't know how to handle concurrency conflicts for "
+ entry.Metadata.Name);
}
}
}
}
}
return NoContent();
}

Change State to EntityState.Modified raised error

I have the following Asp.Net MVC 4 scaffold code.
//
// POST: /Detail/Edit/5
[HttpPost]
public ActionResult Edit(Detail detail)
{
var dd = Details.FirstOrDefault(d => d.DetailId == detail.DetailId);
if (dd == null)
{
return HttpNotFound();
}
detail.UpdatedBy = User.Identity.Name;
detail.UpdateTime = DateTime.Now;
if (ModelState.IsValid)
{
_db.Entry(detail).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index", new { id = detail.MasterId });
}
return View(dealDetail);
}
However, the line _db.Entry(detail).State = EntityState.Modified; raise the following error. What's the correct way to update the detail line of a master/detail editing scenery?
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
This line:
var dd = Details.FirstOrDefault(d => d.DetailId == detail.DetailId);
will cause loading of Detail entity from the database. Now you have two Details with the same Id but only one (the one loaded by that query) can be used for persistence. You can change your code to:
if (!Details.Any(d => d.DetailId == detail.DetailId))
{
return HttpNotFound();
}
or update the attached detail (dd) for example by:
// All values of detail entity must be set in your HTTP post!
_db.Entry(dd).CurrentValues.SetValues(detail);

Entity Framework Error

I have a little problem. I am encountering the following error each time I try update my entityset.
Unable to update the EntitySet 'ShoppingCart' because it has a
DefiningQuery and no InsertFunction element exists in the
ModificationFunctionMapping element to support the current
operation.
The code is: `
public void AddItem(string cartID, string productID, string quantity)
{
using (CommerceEntities db = new CommerceEntities())
{
try
{
var myItem = (from c in db.ShoppingCarts
where c.CartID == cartID &&
c.ProductID == productID
select c).FirstOrDefault();
if (myItem == null)
{
ShoppingCart cartadd = new ShoppingCart();
cartadd.CartID = cartID;
cartadd.Quantity = quantity;
cartadd.ProductID = productID;
cartadd.DateCreated = DateTime.Now;
db.ShoppingCarts.AddObject(cartadd);
}
else
{
myItem.Quantity += Convert.ToInt32(quantity);
}
db.SaveChanges();
}
catch (Exception exp)
{
throw new Exception("ERROR: Unable to Add Item to Cart - " +exp.Message);
}
}
}
`
Please help me. I can provide more information if required, I am new to this Entity Framework Model and following the tutorial on This page.
Update: I added primary keys and redesigned the whole database. Now the error changed to:
System.Data.UpdateException was unhandled by user code Message=An
error occurred while updating the entries. See the inner exception for
details.
This usually happens if entity set is mapped from database view, custom database query or if database table doesn't have primary key.

release_mode, Pooling, Max Pool size for InMemory SQLite with FluentNHibernate

I'm having some trouble with Sqlite in memory.
I have a class that has a CPF field - similar to US' SSN. As a bussiness rule, the CPF must be unique in the system.
So I've decided to make a check on the class that has this field. Now maybe there's code smell here: I check with the ORM if this is a Conflicting CPF.
private CPF cpf;
public virtual CPF CPF
{
get { return cpf; }
set
{
if (this.ormCreated) //Do not check if it is loaded from the DB. Otherwise, it loops, generating a StackOverflow exception
{
cpf = value;
}
else
{
this.setNewCpf(value);
}
}
}
private void setNewCpf(CPF newCpf)
{
if (this.cpf == newCpf)
{
return;
}
if (Helper.Orm.IsConflictingCpf(newCpf))
{
throw new ConflictingCpfException();
}
else
{
cpf = newCpf;
}
}
And here is the implementation, on the ORM Helper class.
bool OrmHelper.IsConflictingCpf(CPF cpf)
{
int? cpfNumber = cpf.NumeroSemDV;
if (cpfNumber.HasValue)
{
var teste = findByCpfNumber<Client>(cpf);
return
(
findByCpfNumber<Client>(cpf) != null ||
findByCpfNumber<Adversary>(cpf) != null
);
}
else
{
//CPFSemDV = Nullable
return false;
}
}
private PersonType findByCpfNumber<PersonType> (CPF cpf) where PersonType : PessoaFisica
{
int? cpfNumber = cpf.NumeroSemDV;
using (var session = this.NewSession())
using (var transaction = session.BeginTransaction())
{
try
{
var person = session.Query<PersonType>()
.Where(c => c.CPF.NumeroSemDV == cpfNumber)
.FirstOrDefault<PersonType>();
return person;
}
catch (Exception) { transaction.Rollback(); }
finally
{
session.Close();
}
}
return null;
}
The problem happens in my tests. I'm using FluentNHibernate and In memory SQLite.
protected override FluentConfiguration PersistenceProvider
{
get
{
return Fluently
.Configure()
.Database(
SQLiteConfiguration
.Standard
.InMemory()
.ShowSql()
);
}
}
Here is the failing test.
protected override void Given()
{
base.Given();
var clients = new List<Client>();
Client client1 = new Client("Luiz Angelo Heinzen")
{
Capaz = true,
CPF = new CPF(18743509),
eMail = "lah#furb.br"
};
session.Save(client1);
session.Evict(client1);
}
[Then]
public void Motherfaker()
{
Client fromDb;
var clientsFromDb = session.Query<Client>()
.Where(c => c.eMail == "lah#furb.br");
fromDb = clientsFromDb.FirstOrDefault<Client>();
Assert.AreEqual(fromDb.FullName, "Luiz Angelo Heinzen");
}
The reason it fails? In the beginning it was failing because the table didn't exist. In memory sqlite destroys the schema on each new session. So I changed the code to return the same session on the NewSession(). But now it fails with a NHibernate exception: Session is closed. I've tested and if change the findByCpfNumber from this
private PersonType findByCpfNumber<PersonType> (CPF cpf) where PersonType : PessoaFisica
{
int? cpfNumber = cpf.NumeroSemDV;
using (var session = this.NewSession())
using (var transaction = session.BeginTransaction())
{
try
{
var person = session.Query<PersonType>()
.Where(c => c.CPF.NumeroSemDV == cpfNumber)
.FirstOrDefault<PersonType>();
return person;
}
catch (Exception) { transaction.Rollback(); }
finally
{
session.Close();
}
}
return null;
}
to this
private PersonType findByCpfNumber<PersonType> (CPF cpf) where PersonType : PessoaFisica
{
int? cpfNumber = cpf.NumeroSemDV;
//using (var session = this.NewSession())
var session = this.NewSession();
using (var transaction = session.BeginTransaction())
{
try
{
var person = session.Query<PersonType>()
.Where(c => c.CPF.NumeroSemDV == cpfNumber)
.FirstOrDefault<PersonType>();
return person;
}
catch (Exception) { transaction.Rollback(); }
finally
{
//session.Close();
this.CloseSession(session);
}
}
this.CloseSession(session);
return null;
}
the error doesn't happen anymore. Obviously, I'd have to implement the CloseSession method. It would close the Session on the Production database and it would do nothing if Sqlite is being used.
But I'd rather configure SQLite in someway that it wouldn't dispose the session. I've read here about release_mode, Pooling and Max Pool atributes. But I can't seem to find it in the FluentNHibernate so can't even test to see if it would work. I have the FluentNHibernate cloned and it seems to set the release_mode set to on_close, but that doesn't help.
I've even tried:
public override ISession NewSession()
{
if (this.session == null)
{
if (sessionFactory == null)
{
CreateSessionFactory();
}
this.session = sessionFactory.OpenSession();
}
if (!session.IsOpen)
{
sessionFactory.OpenSession(session.Connection);
session.Connection.Open();
}
return session;
}
But it keeps telling me that the Session is closed. So, anyone has any suggestions on how to approach this?
Or does this so smelly that's beyond salvation?
I hope this is clear enough. And forgive my mistakes: I'm from Brazil and not a native english speaker.
Thanks,
Luiz Angelo.
i would check for uniqueness when creating CPFs in the system and have an additional Unique constraint in the database to enforce that. Then if you set cascading to none for each reference to CPF (default is none) it is not possible to assigne newly created duplicate CPFs to an Entity and save it without exception, so it can't happen accidently.
I had the same problem. What's happening is that in-memory SQLite will drop the entire schema when the connection is closed. If you create a session that you hold on to for all tests, it will retain the structure for all other sessions.
For code and a fuller explanation, check out this answer: Random error when testing with NHibernate on an in-Memory SQLite db

Resources