how to update a record in database using LINQ? - entity-framework

I want to do the following in LINQ:
update [dbo].[AdminLogin] set [ADMIN_PASSWORD] = 'abc' where [ADMIN_ID] = 1
where i get the admin password from a model and the admin id is stored in a variable:
var userid = (from m in db.RequestPasswordReset
where m.Id == Unid
select m.UserId).FirstOrDefault();
How to do it?

To update an entity you must have to specify the Modified state.
using (var db= new DbContext())
{
var entity= db.AdminLogin.Where(x => x.ADMIN_ID == userid ).SingleOrDefault();
entity.ADMIN_PASSWORD = 'abc';
db.Entry(entity).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
}
see details here

use this code:
using (var context = new YourContext())
{
var res = context.AdminLogin.Where(x => x.ADMIN_ID == userid ).SingleOrDefault();
res.ADMIN_PASSWORD = 'abc';
context.SaveChanges();
}

You can try this:
var user = db.AdminLogin.FirstOrDefault(x => x.ADMIN_ID == id);
user.ADMIN_PASSWORD = 'abc';
db.SaveChanges();

userid.ADMIN_PASSWORD= 'abc';
db.SaveChanges(); //better then db.SubmitChanges() in some case

If you using linQ.dbml file then you have to write like this:
using (var db= new DbContext())
{
var entity= db.AdminLogin.Where(x => x.ADMIN_ID == userid ).FirstOrDefault();
entity.ADMIN_PASSWORD = 'abc';
db.SubmitChanges();
}

Related

The instance of entity type 'x' cannot be tracked because another instance with the same key value for {'a', 'b'} is already being tracked

I got the error in the title while editing relational table between many-to-many relationship. It will not let duplicate on table, so I try to remove rows and then create new one but it didn't work.
public void Update(ThermoformProduct entity, int[] thermoformCategoryIds)
{
using (var context = new ShopContext())
{
var product = context.ThermoformProducts
.Include(i => i.ThermoformProductCategories)
.FirstOrDefault(i => i.ProductId == entity.ProductId);
if (product != null)
{
product.Code = entity.Code;
product.Culture = entity.Culture;
product.Renk = entity.Renk;
product.UstGenislik = entity.UstGenislik;
product.UstCap = entity.UstCap;
product.AltCap = entity.AltCap;
product.TbCap = entity.TbCap;
product.Yukseklik = entity.Yukseklik;
product.Hacim = entity.Hacim;
product.TamHacim = entity.TamHacim;
product.Baski = entity.Baski;
product.SosisIciAdet = entity.SosisIciAdet;
product.KoliIciAdet = entity.KoliIciAdet;
product.ImageUrl = entity.ImageUrl;
product.ThermoformProductCategories.RemoveAll(s=>s.ProductId == product.ProductId);
product.ThermoformProductCategories = thermoformCategoryIds.Select(catid => new ThermoformProductCategory()
{
ProductId = product.ProductId,
ThermoformProduct = product,
CategoryId = catid,
ThermoformCategory = context.ThermoformCategories.Where(i => i.CategoryId == catid).FirstOrDefault()
}).ToList();
context.SaveChanges();
}
}
}
EF cannot track two different instance of an entity type with same primary key. You have included the related ThermoformProductCategory entities, so they are being tracked by the context. When you remove them, they are cleared from the ThermoformProductCategories property of that product, but they are not removed from the context, and are still being tracked. Finally when you create the new list of ThermoformProductCategory, some of the new ones' primary key are matching the previous ones' (which already exist in the context)
Since you are creating the entire list again, you don't need to fetch the related entities in the first place. Simply assign a new list and EF will replace the entire list of related entities -
var product = context.ThermoformProducts.FirstOrDefault(i => i.ProductId == entity.ProductId);
if (product != null)
{
// set all the properties
product.ThermoformProductCategories = thermoformCategoryIds.Select(catid => new ThermoformProductCategory()
{
ProductId = product.ProductId,
CategoryId = catid
}).ToList();
context.SaveChanges();
}
Two things:
The filter is redundant - the ThermoformProductCategories navigation property should already be filtered.
product.ThermoformProductCategories.RemoveAll(s=>s.ProductId == product.ProductId);
instead do this:
product.ThermoformProductCategories.RemoveAll(); // Or .Clear()
Don't set navigation properties in this case, just the foreign key values - this should resolve your issue:
Instead of:
product.ThermoformProductCategories = thermoformCategoryIds.Select(catid => new ThermoformProductCategory()
{
ProductId = product.ProductId,
ThermoformProduct = product,
CategoryId = catid,
ThermoformCategory = context.ThermoformCategories.Where(i => i.CategoryId == catid).FirstOrDefault()
}).ToList();
Do:
product.ThermoformProductCategories = thermoformCategoryIds.Select(catid => new ThermoformProductCategory()
{
ProductId = product.ProductId, // Even this might be redundant since you're adding to the product navigation property list.
CategoryId = catid
}).ToList();
both answers was solution here is my final form if anyone gets trouble
public void Update(ThermoformProduct entity, int[] thermoformCategoryIds)
{
using (var context = new ShopContext())
{
var product = context.ThermoformProducts
.FirstOrDefault(i => i.ProductId == entity.ProductId);
if (product != null)
{
product.Code = entity.Code;
product.Culture = entity.Culture;
product.Renk = entity.Renk;
product.UstGenislik = entity.UstGenislik;
product.UstCap = entity.UstCap;
product.AltCap = entity.AltCap;
product.TbCap = entity.TbCap;
product.Yukseklik = entity.Yukseklik;
product.Hacim = entity.Hacim;
product.TamHacim = entity.TamHacim;
product.Baski = entity.Baski;
product.SosisIciAdet = entity.SosisIciAdet;
product.KoliIciAdet = entity.KoliIciAdet;
product.ImageUrl = entity.ImageUrl;
var cmd = "delete from ThermoformProductCategory where ProductId=#p0";
context.Database.ExecuteSqlRaw(cmd, product.ProductId);
product.ThermoformProductCategories = thermoformCategoryIds.Select(catid => new ThermoformProductCategory()
{
ProductId = product.ProductId,
CategoryId = catid,
ThermoformCategory = context.ThermoformCategories.Where(i => i.CategoryId == catid).FirstOrDefault()
}).ToList();
context.Entry(product).State = EntityState.Modified;
context.SaveChanges();
}
}
}

UpdateRange method of Entity Framework Core does not work

The UpdateRange method of Entity Framework Core is used here to update multiple records but it is not working.
My code is:
var dept1 = new Department()
{
Id = 8,
Name = "New Designing"
};
var dept2 = new Department()
{
Id = 9,
Name = "New Research"
};
var dept3 = new Department()
{
Id = 102,
Name = "New HR"
};
List<Department> modifiedDept = new List<Department>() { dept1, dept2, dept3 };
using (var context = new CompanyContext())
{
context.UpdateRange(modifiedDept);
await context.SaveChangesAsync();
}
And the error I get is:
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: 'Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.'
What should be done in this case?
You are supposed to get data from database and modify data. Not creating new class.
using (var context = new JobContext())
{
var depts = context.Department.Where(x => x.Id > 1).AsQueryable();
depts.Where(x => x.Id == 2).FirstOrDefault().Name = "New Designing";
depts.Where(x => x.Id == 3).FirstOrDefault().Name = "New Research";
depts.Where(x => x.Id == 4).FirstOrDefault().Name = "New HR";
context.UpdateRange(depts);
context.SaveChanges();
}
Before
After

Remove and Insert in table , Removing previous data using Entity frame work in asp.net core

When trying to insert "FromCompany" data to "ToCompany" after saveChanges(); it deleted "FromCompany" data.
I am trying to delete old data , and copy the data from another company to mycompany, but it deleting the data from that comapny after saving it in my company.
This is the example code:
foreach (var data in ctx.AllData.Where(a => a.CompanyId == toCompanyId).Select(a => a).ToList())
{
ctx.AllData.Remove(data);
}
ctx.SaveChanges();
var alldata = ctx.AllData.Where(a => a.CompanyId == fromCompanyId ).Select(a => a).ToList();
foreach (var data in alldata)
{
var model = new AllData();
data.CompanyId = toCompanyId;
model.CompanyId = data.CompanyId;
model.CategoryId = data.CategoryId;
model.OtherFields = data.OtherFields;
ctx.AllData.Add(model);
}
ctx.SaveChanges();
In the second foreach you are changing the data.CompanyId. Then calling ctx.SaveChanges you are changing all companies with fromCompanyId. Try to remove that line, like this:
foreach (var data in ctx.AllData.Where(a => a.CompanyId == toCompanyId).Select(a => a).ToList())
{
ctx.AllData.Remove(data);
}
ctx.SaveChanges();
var alldata = ctx.AllData.Where(a => a.CompanyId == fromCompanyId ).Select(a => a).ToList();
foreach (var data in alldata)
{
var model = new AllData();
model.CompanyId = toCompanyId;
model.CategoryId = data.CategoryId;
model.OtherFields = data.OtherFields;
ctx.AllData.Add(model);
}
ctx.SaveChanges();
While you are calling ctx.SaveChanges you are saving all changes were performed in all context's data.

How do I filter out child collection in EF6.1

I have a Apps, AppRoles, UserAppRoles and Users. I'm trying to Get All Users but only want the AppRoles where AppId = 1. How do I filter the child collection?
using (var context = new dbContext())
{
var rv = context.Users
.Include(u => u.AppRoles);
}
I tried this but throws and exception:
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties
public static async Task<List<User>> GetAllAsync()
{
var rv = new List<User>();
using (var context = new dbContext())
{
rv = await (context.Users.AsNoTracking()
.Include(a => a.AppRoles.Where(a2 => a2.AppId == 1)).ToListAsync());
}
return rv;
}
The only way I could figure out how to get it to work is like this which I might as well just use a stored procedure at that point:
var rv = new List<User>();
using (var context = new dbContext())
{
rv = context.Users.AsNoTracking()
.Include(a => a.AppRoles).ToList();
}
foreach (var user in rv)
{
if (user.AppRoles.Any())
{
user.AppRoles = user.AppRoles.Where(r2 => r2.AppId == 1).ToList();
}
}
How do I write this in EF?
SELECT
Users.UserId,
Users.UserName
FROM
Users
INNER JOIN UserAppRoles ON Users.UserId = UserAppRoles.UserId
INNER JOIN AppRoles ON UserAppRoles.AppRoleId = AppRoles.AppRoleId
WHERE AppRoles.AppId = 1
Try this:
context.Entry(user)
.Collection(b => b.AppRoles)
.Query()
.Where(r => r.AppId==1)
.Load();
where user is an AppUser entity from the context (like in your foreach example).
More info here:
https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx ("Applying filters when explicitly loading related entities" section)
You might subquery the AppRoles
var arQuery = from ar in context.AppRoles
where ar.AppId == 1
select ar;
var query = from u in context.Users
join uar in context.UserAppRoles on u.UserId equals uar.UserId
join ar in arQuery on uar.AppRoleId equals ar.AppRoleId
select u;
I have this working like this but still seems inefficient but guess it's better than round trips to database. Isn't this a common pattern? I can't believe a simple inner join isn't included in EF but I'm mapping to DTOs anyways so guess this will work for now until I look into a few open source Include filters that support filtering.
var rv = context.Users.Include(r => r.AppRoles).ToList().Select(u => new User()
{
UserId = u.UserId,
AppRoles = u.AppRoles.Where(x=>x.AppId == 1).ToList()
});
Disclaimer: I'm the owner of the project Entity Framework Plus
The EF+ Query IncludeFilter allow easily filter included entities.
public static async Task<List<User>> GetAllAsync()
{
var rv = new List<User>();
using (var context = new dbContext())
{
rv = await (context.Users.AsNoTracking()
.IncludeFilter(a => a.AppRoles.Where(a2 => a2.AppId == 1)).ToListAsync());
}
return rv;
}
Wiki: EF+ Query Include Filter

Not able to access list of record in EF

Here is the problem I am trying to access some records from the data base based on one field . The field I am using is audit_id having type GUID .
but the line does not returning any data
var audits = ctx.Audits.Where(x => lstAudits.Contains(x.audit_id)).ToList();
Here is a my full code to update mass records in the database using EF
//will select auditId from the List
var lstAudits = _ViewModel.WorkingListAudits.Where(x => x.WorkingList).Select(x=>x.AuditId).ToList();
using (var ctx = new AuditEntities())
{
var audits = ctx.Audits.Where(x => lstAudits.Contains(x.audit_id)).ToList();
audits.ForEach(x => x.working_list = false);
ctx.SaveChanges();
}
In case of single record it return data from database
var lstAudits = _ViewModel.WorkingListAudits.Where(x => x.WorkingList).Select(x => x.AuditId).ToList();
Guid tempAuditId = lstAudits[0];
// lstAudits.ForEach(x => x.ToString().ToUpper());
using (var ctx = new AuditEntities())
{
var audits = (from au in ctx.Audits
where au.audit_id == tempAuditId
select au).ToList();
//foreach(Audit audit in audits){
//}
audits[0].working_list = false;
ctx.SaveChanges();
}
Finally I got the answer here is the updated code which is working fine .I just took some intermediate result in a temporary variable and it started working as expected
//will select auditId from the List
var lstAudits = _ViewModel.WorkingListAudits.Where(x => x.WorkingList).Select(x => x.AuditId).ToList();
using (var ctx = new AuditEntities())
{
var tempAudits = ctx.Audits.ToList();
var audits = tempAudits.Where(x => lstAudits.Contains(x.audit_id)).ToList();
audits.ForEach(x => x.working_list = false);
ctx.SaveChanges();
}