I am inserting objects at the same time using Entity framework like below.
context = new MyContext();
foreach (var x in lstX)
{
var abc = new abc{ name= x.abcName };
context.abcs.Add(abc);
var xyz = new xyz{ name = x.xyzName };
context.xyzs.Add(xyz);
}
context.SaveChanges();
Is it possible get the identity of all these inserted objects?
When you call SaveChanges, the Identity field is populated on the original entity. So to obtain this id, simply store a reference to the identity and access it after SaveChanges:
context = new MyContext();
List<abc> addedABCs = new List<abc>();
List<xyz> addedXYZs = new List<xyz>();
foreach (var x in lstX)
{
var abc = new abc{ name= x.abcName };
addedABCs.Add(abc);
context.abcs.Add(abc);
var xyz = new xyz{ name = x.xyzName };
addedXYZs.Add(xyz);
context.xyzs.Add(xyz);
}
context.SaveChanges();
foreach (var abc in addedABCs)
{
Console.WriteLine("Added item with ID {0}", abc.Id);
}
Related
List< IletisimLog> bulkInsertIletisimLog = new List<IletisimLog>();
//there are 1000 values in the array of paramaters
foreach (var kId in paramaters)
{
var iletisimLogInsert = new IletisimLog()
{
KullaniciID = kId.KullaniciId,
EklendigiTarih = DateTime.Now,
GonderildigiTarih = DateTime.Now,
BilgilendirmeTurID = bilgilendirmeturId,
};
bulkInsertIletisimLog.Add(iletisimLogInsert);
}
_iLetisimLogService.BulkInsertRange(bulkInsertIletisimLog);
There are 1000 records registered in the database. How to get the primary key value for each record
As you loop through the Entities to add them to the database, if there is a primary key on there, the Id that is assigned to each will be reflected in the object.
List< IletisimLog> bulkInsertIletisimLog = new List<IletisimLog>();
//there are 1000 values in the array of paramaters
foreach (var kId in paramaters)
{
var iletisimLogInsert = new IletisimLog()
{
KullaniciID = kId.KullaniciId,
EklendigiTarih = DateTime.Now,
GonderildigiTarih = DateTime.Now,
BilgilendirmeTurID = bilgilendirmeturId,
};
bulkInsertIletisimLog.Add(iletisimLogInsert);
}
_iLetisimLogService.BulkInsertRange(bulkInsertIletisimLog);
foreach (var inserted in bulkInsertIletisimLog)
{
// Get the ID of the inserted object
var newId = inserted.Id;
}
Assuming primary key value on your object is called Id.
I look for a way of executing RemoveRange() with 1-query-approach. With Remove() method it works like this:
public void Delete()
{
Record record = new Record() {
id = 1,
value = 5
};
using(SomeContext ctx = new SomeContext()) {
ctx.Records.Entry(record).State = EntityState.Deleted;
ctx.SaveChanges();
}
}
But the same approach doesn't work for RemoveRange(). EF documentation says that the method sets each entity to EntityState.Deleted. If it would be so as I understand it - this would work:
public void DeleteAll()
{
List<Record> records = new List<Record>() {
new Record() { id = 1, value = 5 },
new Record() { id = 2, value = 10 }
};
using(SomeContext ctx = new SomeContext()) {
ctx.Records.RemoveRange(records);
ctx.SaveChanges();
}
}
because this works:
public void DeleteAll()
{
List<Record> records = new List<Record>() {
new Record() { id = 1, value = 5 },
new Record() { id = 2, value = 10 }
};
using(SomeContext ctx = new SomeContext()) {
foreach(var item in records)
{
ctx.Entry(item).State = EntityState.Deleted;
}
ctx.SaveChanges();
}
}
But it doesn't and throws the exception
The object cannot be deleted because it was not found in the ObjectStateManager.
Can I use this method without retrieving all of them from database via separate query?
When you use ctx.Entry(item) it adds this item to the context tracking and then you can edit it. With RemoveRange it does not implicitly add to the data context first and that is why you get the exception.
Try using AttachRange before RemoveRange
Edit:
Alternative way to do it. This is a bit how RemoveRange does it behind the scenes. It first disables AutoDetectChanges, removes what it should and then calls DetectChanges. Could wrap this in an extension method to make it a one liner again.
public void DeleteAll()
{
List<Record> records = new List<Record>() {
new Record() { id = 1, value = 5 },
new Record() { id = 2, value = 10 }
};
using(SomeContext ctx = new SomeContext()) {
ctx.Configuration.AutoDetectChangesEnabled = false;
foreach(var item in records)
{
ctx.Entry(item).State = EntityState.Deleted;
}
ctx.ChangeTracker.DetectChanges();
ctx.SaveChanges();
}
}
As I found your entity-collection is detached(as you creating it there) so objectContext not tracking it. You may need to attach it. you can do this as below:
//Find all records in database with an id that is in your record collection
var recordsToBeDeleted = ctx.Records.Where(dbr => records.Any(r => r.id == dbr.id));
ctx.Records.RemoveRange(recordsToBeDeleted);
context.SaveChanges();
Solution taken from this thread
When updating the Viewers collection with a reference to a User with the Id correctly set the DB is not updated with this new reference. All other fields are updated but the collections are not updated.
var entity = new Event
{
Id = model.Id,
Name = model.Name,
Date = model.Date,
Location = model.Location,
EBroadcasters = model.Broadcasters?.Select(b => new User
{
Id = b.Id,
SkypeId = b.SkypeId,
Name = b.Name,
ServiceUrl = b.ServiceUrl
}).ToList(),
EViewers = model.Viewers?.Select(v => new User
{
Id = v.Id,
SkypeId = v.SkypeId,
Name = v.Name,
ServiceUrl = v.ServiceUrl
}).ToList()
};
_ssRepository.Events.Attach(entity);
_ssRepository.Entry(entity).State = EntityState.Modified;
// Don't think I need to do this stuff but tried everything to get it to update!!!
foreach (var b in entity.EBroadcasters)
{
_ssRepository.Users.Attach(b);
_ssRepository.Entry(b).State = EntityState.Modified;
}
foreach (var v in entity.EViewers)
{
_ssRepository.Users.Attach(b);
_ssRepository.Entry(v).State = EntityState.Modified;
}
_ssRepository.SaveChanges();
Any help would be greatly appreciated!
Gerard
I have two tables in an SQL database. They both have five fields: ID (PK), Number, InvoiceDate, InvoiceNumber, and InvoiceAmount. I am attempting to use Entity Framework to insert the InvoiceDate, InvoiceNumber, and InvoiceAmount where the field Number matches from one table to the other.
The context for table one is:
var tc = new TemporaryCsvUpload();
Table two:
var pt = new PermanentTestTable();
First, I inserted values into table 1 from a CSV, now I am trying to insert into table two where the Number field matches.
var entity = new CsvDbEntities1();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload();
tc.Number = item.Number;
tc.CreditInvoiceAmount = item.CreditInvoiceAmount;
tc.CreditInvoiceDate = item.CreditInvoiceDate;
tc.CreditInvoiceNumber = item.CreditInvoiceNumber;
entity.TemporaryCsvUploads.Add(tc);
entity.SaveChanges();
}
I am new to EF and any help would be appreciated. Thanks!
Sorry if I dont completely understand but here it goes based of this code :
foreach (var item in model)
{
var tc = new TemporaryCsvUpload();
tc.Number = item.Number;
tc.CreditInvoiceAmount = item.CreditInvoiceAmount;
tc.CreditInvoiceDate = item.CreditInvoiceDate;
tc.CreditInvoiceNumber = item.CreditInvoiceNumber;
entity.TemporaryCsvUploads.Add(tc);
entity.SaveChanges();
}
After you have saved the first table now you query the second for the same record as :
var table2entity = entity.PermanentTestTable.Where(x => x.Number == tc.Number).Select(x => x).First();
This will query the second table and grab whatever entity is there with the same number
So your end code might look like :
var entity = new CsvDbEntities1();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload();
tc.Number = item.Number;
tc.CreditInvoiceAmount = item.CreditInvoiceAmount;
tc.CreditInvoiceDate = item.CreditInvoiceDate;
tc.CreditInvoiceNumber = item.CreditInvoiceNumber;
entity.TemporaryCsvUploads.Add(tc);
entity.SaveChanges();
var table2entity = entity.PermanentTestTable.ToList();
table2entity = table2entity.Where(x => x.Number == tc.Number).Select(x => x).First();
table2entity.CreditInvoiceAmount = item.CreditInvoiceAmount;
//More values inserted here
entity.SaveChanges()
}
I ended up having to nest a foreach loop to iterate through every row with a Number field. I'm sure there is a better way to do this, but I am just happy it's working:
var entity = new CsvDbEntities1();
foreach (var item in model)
{
var tc = new TemporaryCsvUpload
{
PoNumber = item.Number,
CreditInvoiceAmount = item.CreditInvoiceAmount,
CreditInvoiceDate = item.CreditInvoiceDate,
CreditInvoiceNumber = item.CreditInvoiceNumber
};
entity.TemporaryCsvUploads.Add(tc);
var ptt = entity.PermanentTestTables.ToList().Where(x => x.Number == tc.Number);
foreach (var row in ptt)
{
row.CreditInvoiceDate = tc.CreditInvoiceDate;
row.CreditInvoiceNumber = tc.CreditInvoiceNumber;
row.CreditInvoiceAmount = tc.CreditInvoiceAmount;
}
entity.SaveChanges();
}
I am trying to get all the ID's after adding a new rows in the DB.
I tried this but gives me an exception -> return 0 for Id
foreach (var s in ss)
{
Table t1 = new Table();
...
...
_entities.Table.Add(t1);
Ids.Add(ID); // <--- trying to get Ids here.
}
_entities.SaveChanges();
TIA
Generally, your entities will have an ID property, which is updated after you call SaveChanges(). So you could do this:
List<int> Ids = new List<int>();
foreach (var s in ss)
{
Table t1 = new Table();
...
_entities.Table.Add(t1);
_entities.SaveChanges();
Ids.Add(t1.ID);
}
Or this:
List<Table> insertedTables = new List<Table>();
foreach (var s in ss)
{
Table t1 = new Table();
...
_entities.Table.Add(t1);
insertedTables.Add(t1);
}
_entities.SaveChanges();
List<int> Ids = insertedTables.Select(t => t.ID).ToList();