How to overwrite data in the database? [ASP.NET] - c#

This code saves my data to the database. The app records the time spent on each day of the month.
They write to the database in SQL Server, using EF. The problem is just that I would like them to overwrite instead of writing more
Controller:
List<Karta_Model> objNextKartaModel = new List<Karta_Model>();
for (int i = 0; i < liczbaDni; i++)
{
var modelNext = new Karta_Model()
{
Login = userName,
Rok = numerRoku,
Miesiac = numerMiesiaca,
DzMiesiaca = modelKarta.Model1[i].DzMiesiaca.Value,
DzTygodnia = modelKarta.Model1[i].DzTygodnia,
Rozpoczecie = modelKarta.Model1[i].Rozpoczecie
....
};
objNextKartaModel.Add(modelNext);
await _ecpContext.Karta.AddRangeAsync(objNextKartaModel);
await _ecpContext.SaveChangesAsync();
}
Id in SQL Server is defined as:
[Id] [int] IDENTITY(1,1)
I came up with the idea to extract the first row ID from the previously saved database
var nrIdBase = _ecpContext.Karta
.FirstOrDefault(f => f.DzMiesiaca == 1 &&
f.Miesiac == numerMiesiaca &&
f.Rok == numerRoku &&
f.Login == userName).Id;
but I don't know how to use it.
I tried something like this:
for (int i = 0; i < liczbaDni; i++)
{
var modelNext = new Karta_Model()
{
Id = nrIdBase +i,
Login = userName,
Rok = numerRoku,
Miesiac = numerMiesiaca,
DzMiesiaca = modelKarta.Model1[i].DzMiesiaca.Value,
DzTygodnia = modelKarta.Model1[i].DzTygodnia,
Rozpoczecie = modelKarta.Model1[i].Rozpoczecie
....
};
}
but I get an error:
InvalidOperationException: The instance of entity type 'Karta_Model' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
Does anyone have an idea how to do this?
How to overwrite saved data once?

In order to update an existing recording in a database, you need to have it's ID before the update operation.
Then you can do this:
var existingRecord = _ecpContext.Karta.FirstOrDefault(x => x.Id == theExistingId);
if (existingRecord != null) {
existingRecord.Login = "CHANGED";
await _ecpContext.SaveChangesAsync()
}
This call that you are using:
await _ecpContext.Karta.AddRangeAsync(objNextKartaModel);
Is only for adding new items to the database.

Following the idea in my comment above, one thing you can do is to delete the existing data in the table before adding the new ones.
List<Karta_Model> objNextKartaModel = new List<Karta_Model>();
for (int i = 0; i < liczbaDni; i++)
{
var modelNext = new Karta_Model()
{
Login = userName,
Rok = numerRoku,
Miesiac = numerMiesiaca,
DzMiesiaca = modelKarta.Model1[i].DzMiesiaca.Value,
DzTygodnia = modelKarta.Model1[i].DzTygodnia,
Rozpoczecie = modelKarta.Model1[i].Rozpoczecie
....
};
objNextKartaModel.Add(modelNext);
//Add logic to delete the existing data
foreach(var model in _ecpContext.Karta)
{
_ecpContext.Karta.Remove(model);
}
await _ecpContext.Karta.AddRangeAsync(objNextKartaModel);
await _ecpContext.SaveChangesAsync();//One SaveChanges call is enough to update the database
}

Related

How to add distinct value in database using Entity Framework

IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
}
}
db.SaveChanges();
I want to add only distinct values to database in above code. Kindly help me how to do it as I am not able to find any solution.
IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
var a = db.WebsiteWebPages.Where(i => i.WebPage == value.WebPage.ToString()).ToList();
if (a.Count == 0)
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
db.SaveChanges();
}
}
}
This is the code that I used to add distinct data.I hope it helps
In addition to the code sample Furkan Öztürk supplied, Make sure your DB has a constraint so that you cannot enter duplicate values in the column. Belt and braces approach.
I assume that by "distinct values" you mean "distinct value.WebPage values":
// get existing values (if you ever need this)
var existingWebPages = db.WebsiteWebPages.Select(v => v.WebPage);
// get your pages
var webPages = GetWebPages().Where(v => v.WebPage.Contains(".htm"));
// get distinct WebPage values except existing ones
var distinctWebPages = webPages.Select(v => v.WebPage).Distinct().Except(existingWebPages);
// create WebsiteWebPage objects
var websiteWebPages = distinctWebPages.Select(v =>
new WebsiteWebPage { WebPage = v, WebsiteId = websiteid});
// save all at once
db.WebsiteWebPages.AddRange(websiteWebPages);
db.SaveChanges();
Assuming that you need them to be unique by WebPage and WebSiteId
IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
if (db.WebsiteWebPages.All(c=>c.WebPage != value.WebPage|| c.WebsiteId != websiteid))
{
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
}
}
}
db.SaveChanges();
UPDATE
To optimize this (given that your table contains much more data than your current list), override your equals in WebsiteWebPage class to define your uniqueness criteria then:
var myWebsiteWebPages = data.select(x=> new WebsiteWebPage { WebPage = x.WebPage, WebsiteId = websiteid}).Distinct();
var duplicates = db.WebsiteWebPages.Where(x=> myWebsiteWebPage.Contains(x));
db.WebsiteWebPages.AddRange(myWebsiteWebPages.Where(x=> !duplicates.Contains(x)));
this is a one database query to retrieve ONLY duplicates and then removing them from the list
You can use the following code,
IEnumerable<WebsiteWebPage> data = GetWebPages();
var templist = new List<WebsiteWebPage>();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
templist.Add(pagesinfo);
}
}
var distinctList = templist.GroupBy(x => x.WebsiteId).Select(group => group.First()).ToList();
db.WebsiteWebPages.AddRange(distinctList);
db.SaveChanges();
Or you can use MoreLINQ here to filter distinct the list by parameter like,
var res = tempList.Distinct(x=>x.WebsiteId).ToList();
db.WebsiteWebPages.AddRange(res);
db.SaveChanges();

Entity Framework update DB problem when use AutoDetectChangesEnabled=false

I use Entity Framework and stored procedures.
modelBuilder.Entity<MyModel>().MapToStoredProcedures();
I used Insert update and delete without any problem.but for some purpose I want to use AutoDetectChangesEnabled = false;
After that entity doesn't work anymore and nothing changes in the database after SaveChanges. But when I comment AutoDetectChangesEnabled or set it to true, it works fine.
This is my code: I read from Excel and import into database:
dt = exc.ReadExcel(address, ".xlsx");
using (var db = new Context())
{
db.Configuration.AutoDetectChangesEnabled = false;
for (int i = 1; i < dt.Rows.Count; i++)
{
int id = int.Parse(dt.Rows[i][0].ToString());
var thisChah = db.MyModel.Find(id);
if (thisChah == null)
{
continue;
}
thisChah.f1 = dt.Rows[i][1].ToString();
thisChah.f2 = dt.Rows[i][2].ToString();
thisChah.f3 = dt.Rows[i][3].ToString();
thisChah.f4 = dt.Rows[i][4].ToString();
thisChah.f5 = dt.Rows[i][5].ToString();
thisChah.f6 = dt.Rows[i][6].ToString();
thisChah.f7 = dt.Rows[i][7].ToString();
LogsAnyThing("row " + i + "- OK ");
if(i % 50 == 0)
{
int result = db.SaveChanges();
if (result > 0)
{
LogsAnyThing("row " + i + "- Added ");
}
}
}
db.SaveChanges();
}
Since you have turned off AutoDetectChanges , you need to explicitly tell context to look for any changes before attempting to call SaveChanges(). You can do this by adding this statement - db.ChangeTracker.DetectChange() before call to db.SaveChanges(). Without this context is not aware that any changes has been done to the model.
You can read more #https://learn.microsoft.com/en-us/ef/ef6/saving/change-tracking/auto-detect-changes

Entity Framework inserts only one record

I'm saving a record in my database by passing 3 parameters, the number parameter is passed to pick the number of records from one table to another table. However the loop written inserts only 1 record instead of the number parameter passed.
I'm using the the Take() method in Entity Framework to pick the records. It inserts only the last records in the loop
public async Task<bool> Save(string company, int number, string registrationNumber)
{
using (var trans = _dbContext.Database.BeginTransaction())
{
var db = new SibaCiidDbContext();
var dbSet = _dbContext.Set<IntermediaryAssignment>();
// pick number of records
var data = await (from s in db.StickerDistributions
where s.Dispatched == false &&
s.CompanyCode == company
select s).Take(number).ToListAsync();
var intermediary = (await _repo.FindBy(s => s.RegistrationNumber == registrationNumber &&
s.Status == EntityStatus.Active)).FirstOrDefault();
var entity = new IntermediaryAssignment();
foreach (var sticker in data)
{
entity.CompanyCode = sticker.CompanyCode;
entity.StickerCode = sticker.StickerCode;
entity.RegistrationNumber = intermediary.RegistrationNumber;
entity.Status = EntityStatus.Active;
entity.CreatedDate = DateTime.Now;
entity.Dispatched = false;
entity.IntermediaryType = intermediary.IntermediaryType;
dbSet.Add(entity);
}
trans.Commit();
return await _dbContext.SaveChangesAsync() > 0;
}
}
You are creating one entity, and then updating it 3 times. You need to create a new entity for each new record.
Move the new IntermediaryAssignment() inside the loop.
foreach (var sticker in data)
{
var entity = new IntermediaryAssignment();
entity.CompanyCode = sticker.CompanyCode;
entity.StickerCode = sticker.StickerCode;
entity.RegistrationNumber = intermediary.RegistrationNumber;
entity.Status = EntityStatus.Active;
entity.CreatedDate = DateTime.Now;
entity.Dispatched = false;
entity.IntermediaryType = intermediary.IntermediaryType;
dbSet.Add(entity);
}

C# Create employee. Save to SQL Database using EF

I'm saving an employee to a SQL database. I'm saving Firstname, Lastname, Username and Password. How should I do this to prevent saving more than one identical username?
I've tried this:
private void CreateEmployee()
{
using (var db = new TidrapportDBEntities())
{
var user = (from p
in db.Login
where p.username != null
select p).ToList();
foreach (var vUser in user)
{
if (vUser.username == textBoxUsername.Text)
{
labelSuccessFail.Visible = true;
labelSuccessFail.Text = "Accountname already exist.";
break;
}
else
{
var userInfo = new Login();
var persInfo = new PersonalInformation();
persInfo.firstname = textBoxFirstname.Text;
persInfo.lastname = textBoxLastname.Text;
userInfo.username = textBoxUsername.Text;
userInfo.password = textBoxPassword.Text;
userInfo.employeeId = persInfo.employeeId;
db.Login.Add(userInfo);
db.PersonalInformation.Add(persInfo);
db.SaveChanges();
textBoxFirstname.Text = string.Empty;
textBoxLastname.Text = string.Empty;
textBoxUsername.Text = string.Empty;
textBoxPassword.Text = string.Empty;
labelSuccessFail.Visible = true;
labelSuccessFail.Text = "Successfully created account.";
}
}
}
}
Any tips what I can try?
Kind regards,
Kristian
You should have a unique constraint on the username field. Not sure if you're doing code first, model first or DB first in your EF, but you should be able to google how to get it set on your database using the right method. That will throw an exception if you try to save one, so that makes sure you can't have more than one.
You could also use LINQ statement to restrict the list of users to the user name you wish to create and then you're just down to checking a bool to see if a row is returned or not. That way you're not having to read the entire database table (which your "toList" is doing).
In your code example, you're getting all the users where they have a user name, you're then looping round them, but your conditional code only really works if the first one matches the user name you're trying to save, otherwise you are going to try and recreate a duplicate the second time around. So just to get your code working you could try:
private void CreateEmployee()
{
using (var db = new TidrapportDBEntities())
{
var user = (from p
in db.Login
where p.username != null
select p).ToList();
bool found = false;
foreach (var vUser in user)
{
if (vUser.username == textBoxUsername.Text)
{
found = true;
labelSuccessFail.Visible = true;
labelSuccessFail.Text = "Accountname already exist.";
break;
}
}
if(!found)
{
var userInfo = new Login();
var persInfo = new PersonalInformation();
persInfo.firstname = textBoxFirstname.Text;
persInfo.lastname = textBoxLastname.Text;
userInfo.username = textBoxUsername.Text;
userInfo.password = textBoxPassword.Text;
userInfo.employeeId = persInfo.employeeId;
db.Login.Add(userInfo);
db.PersonalInformation.Add(persInfo);
db.SaveChanges();

FOREIGN_KEY constraint exception

I have an asp.net application with a c# code-behind, connected to an SQL db with linq-to-entities... When I attempt to 'SaveChanges()' on the following code I get an exception (listed below). Any thoughts on what is up?
private void setNewRide(long newRideID, int carNum)
{
handleCompletedRide(carNum);
using (myEntities = new RamRideOpsEntities())
{
Vehicle assignedCar = myEntities.Vehicles.FirstOrDefault(car => car.CarNum == carNum);
Ride newRide = myEntities.Rides.FirstOrDefault(ride => ride.identity == newRideID);
if (assignedCar != null && newRide != null)
{
vs_CurrentRideId = newRide.identity; //Save current ride to ViewState
vs_CarStatus = assignedCar.Status; //Save old status to ViewState
assignedCar.Status = "EnRoute";
assignedCar.CurrPassengers = newRide.NumPatrons;
assignedCar.StartAdd = newRide.PickupAddress;
assignedCar.EndAdd = newRide.DropoffAddress;
assignedCar.CurrentAdd = newRide.DropoffAddress;
assignedCar.Rides.Add(newRide);
newRide.TimeDispatched = DateTime.Now;
newRide.WaitTime = (((DateTime)newRide.TimeDispatched) - ((DateTime)newRide.TimeOfCall));
newRide.AssignedCar = carNum;
newRide.Status = "EnRoute";
myEntities.SaveChanges(); //EXCEPTION HERE!
SelectCarUP.DataBind();
SelectCarUP.Update();
}
}
}
THE EXCEPTION:
The UPDATE statement conflicted with the FOREIGN KEY constraint
\"FK_Rides_Vehicles\". The conflict occurred in database
\"CWIS29RamRideOps\", table \"dbo.Vehicles\", column
'Identity'.\r\nThe statement has been terminated.
THE DB:
This line:
assignedCar.Rides.Add(newRide);
is translated as SQL-INSERT - while you already have a record with the same ID. Decide what you want to do: insert a new ride (in which case you should NULLify the id of newRide), or update it (in which case you should just comment that line out; changes will be saved).
Change your code like this:
newRide.TimeDispatched = DateTime.Now;
newRide.WaitTime = (((DateTime)newRide.TimeDispatched) - ((DateTime)newRide.TimeOfCall));
newRide.AssignedCar = carNum;
newRide.Status = "EnRoute";
assignedCar.Status = "EnRoute";
assignedCar.CurrPassengers = newRide.NumPatrons;
assignedCar.StartAdd = newRide.PickupAddress;
assignedCar.EndAdd = newRide.DropoffAddress;
assignedCar.CurrentAdd = newRide.DropoffAddress;
assignedCar.Rides = newRide; // Your First Change here
myEntities.SaveChanges();

Categories