Why does DbContext FirstOrDefault ignore entities that have been added? - entity-framework-5

I want to search an entityset for objects that I have added to it - but it cant find the object
When I call this proc multiple times with the same entitytypename it always adds a new object. Why?
private EntityRegister GetEntityRegister(string entityTypeName)
{
var er = Db.EntityRegisters.FirstOrDefault(e => e.Name == entityTypeName);
if (er == null)
{
er = new EntityRegister()
{
Name = entityTypeName
};
Db.EntityRegisters.Add(er);
}
return er;
}

Did you save changes? FirstOrDefault goes to the database if you did not save changes the newly added entity is not in the database and therefore FirstOrDefault returns null.

Related

when saving the values of an array in CoreData, only one value is saved

I have an array which I want to add to a CoreData database, I have made a forEach to go through the array and then save the data in CoreData, the problem that only saves a value, below I write the code, There is a problem in the code?
class AquarisB: NSManagedObject, Identifiable {
#NSManaged public var nombre : String
}
struct Inici: View {
var body: some View {
var data : Array = [nombre: test1, nombre: test2]
var nuevoAcuari = Aquaris(context: self.contexto)
#Environment(\.managedObjectContext) var contexto
data.forEach { (temp) in
nuevoAcuari.nombre = temp.nombre
}
do {
try self.contexto.save()
} catch let error as NSError {
print("error al guardar", error.localizedDescription)
}
}
}
As I said in my comment, you need to create a new entity for each item in your data array. Something like this should be enough.
for nombre in data {
var nuevoAcuari = Aquaris(context: contexto)
nuevoAcuari.nombre = nombre
}
do {
try self.contexto.save()
} catch let error as NSError {
print("error al guardar", error.localizedDescription)
}
The managed object context acts as a scratch pad, each time you create an object on it, it is not saved until you call save on it explicitly. If you want to add multiple items then you need to create them and then call save.
In your code all you are doing is updating the object that you have created and then calling save on it. You need to create an object for each item that that you wish to save.

Error: Reference Nbr. cannot be found in the system.."}

I customized the ARPaymentEntry in which it creates a Journal Voucher Entry with created Credit Memo, it retrieves the Credit Memo applies the open invoice that is also applied in the current payment. when I create the instance to call the Credit Memo and add the Invoice in ARAdjust table, an error occurs when trying to insert it, giving a Reference Nbr cannot be found in the system, although when I'm trying to manually applying it I could see the open invoice.
public void ReleaseCreditMemo(string refNbr)
{
try
{
ARPaymentEntry docGraph = PXGraph.CreateInstance<ARPaymentEntry>();
List<ARRegister> list = new List<ARRegister>();
ARPayment payment;
ARRegister invoice = PXSelect<ARRegister, Where<ARRegister.docType, Equal<Required<ARRegister.docType>>, And<ARRegister.refNbr, Equal<Required<ARRegister.refNbr>>>>>.Select(docGraph, ARInvoiceType.CreditMemo, refNbr);
docGraph.Document.Current = PXSelect<ARPayment, Where<ARPayment.docType, Equal<Required<ARPayment.docType>>, And<ARPayment.refNbr, Equal<Required<ARPayment.refNbr>>>>>.Select(docGraph, ARInvoiceType.CreditMemo, refNbr);
payment = docGraph.Document.Current;
list.Add(payment);
foreach (ISARWhTax item in ARWhLine.Select())
{
decimal? _CuryAdjgAmt = payment.CuryOrigDocAmt > invoice.CuryDocBal ? invoice.CuryDocBal : payment.CuryOrigDocAmt;
decimal? _CuryAdjgDiscAmt = payment.CuryOrigDocAmt > invoice.CuryDocBal ? 0m : invoice.CuryDiscBal;
ARAdjust adj = new ARAdjust();
adj.AdjdBranchID = item.AdjdBranchID;
adj.AdjdDocType = ARInvoiceType.Invoice;
adj.AdjdRefNbr = item.AdjdRefNbr;
adj.AdjdCustomerID = item.CustomerID;
adj.AdjdDocDate = invoice.DocDate;
adj.CuryAdjgAmt = _CuryAdjgAmt;
adj.CuryAdjdDiscAmt = _CuryAdjgDiscAmt;
if (docGraph.Document.Current.CuryUnappliedBal == 0m && docGraph.Document.Current.CuryOrigDocAmt > 0m)
{
throw new PXLoadInvoiceException();
}
//This line code below OCCURS THE ERROR
docGraph.Adjustments.Insert(adj);
}
docGraph.Save.Press();
PXLongOperation.StartOperation(docGraph, delegate() { ARDocumentRelease.ReleaseDoc(list, false); });
}
catch (Exception ex)
{
throw new PXException(ex.Message);
}
}
I would look at the selector of the field causing the error ("Reference Nbr.") as having a selector on a field will validate the entered value to the selector's select statement (unless validatevalue=false for the selector). Maybe the selector will give you some pointers as to what is missing or causing the validation to fail.
I figured it out it that after the code below executes it does not immediately updates the View. So what I did is to execute my code at ARPayment_RowSelected event with a conditional statement if the document is released.
PXLongOperation.StartOperation(this.Base, delegate() { ARDocumentRelease.ReleaseDoc(list, false); });

Entity Framework Context.Configuration.AutoDetectChangesEnabled update issue?

I have to import about 30 lacks of data from spreadsheet into the MSSQL DB. I used Entity Framework for Insert/ Update records into the database. But the default entity framework configuration was very slow performance. The constraint is, I need to verify the record before inserting into the table. If it existed then it should update with new values else it should insert new record into the database. But it is taking very large amount of time to Insert/Update records into database. I found a solution to speed up this process here.
Context.Configuration.AutoDetectChangesEnabled = false;
Above setting makes a huge difference in speed.
But the big problems, Records are not updated in table when I set AutoDetectChangesEnabled to false, but inserting is fully functional.
Anyone else seeing this problem? Does anybody help to solve this problem?
I have fixed this issue by using the below code. entry.State becoming to Unchanged when AutoDetectChangesEnabled set to false.
public virtual void Update(T entity)
{
//DbSet.Attach(entity);
//context.Entry(entity).State =EntityState.Modified;
if (entity == null)
{
throw new ArgumentException("Cannot add a null entity.");
}
var entry = context.Entry<T>(entity);
if (entry.State == EntityState.Detached)
{
var pkey = DbSet.Create().GetType().GetProperty(entity.GetType().Name + "ID").GetValue(entity);
var set = context.Set<T>();
T attachedEntity = set.Find(pkey); // You need to have access to key
if (attachedEntity != null)
{
var attachedEntry = context.Entry(attachedEntity);
attachedEntry.CurrentValues.SetValues(entity);
}
else
{
entry.State = EntityState.Modified; // This should attach entity
}
}
else if (entry.State == EntityState.Unchanged)
{
entry.State = EntityState.Modified;
}
}`

Creating a unattached Entity Framework DbContext entity

So I'm working on an app that will select data from one database and update an identical database based on information contained in a 'Publication' Table in the Authoring database. I need to get a single object that is not connected to the 'Authoring' context so I can add it to my 'Delivery' context.
Currently I am using
object authoringRecordVersion = PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).Find(record.RecordId);
object deliveryRecordVersion = PublishingFactory.DeliveryContext.Set(recordType.Entity.GetType()).Find(record.RecordId));
to return my records. Then if the 'deliveryRecordVersion' is null, I need to do an Insert of 'authoringRecordVersion' into 'PublishingFactory.DeliveryContext'. However, that object is already connected to the 'PublishingFactory.AuthoringContext' so it won't allow the Add() method to be called on the 'PublishingFactory.DeliveryContext'.
I have access to PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).AsNoTracking()
but there is no way to get at the specific record I need from here.
Any suggestions?
UPDATE:
I believe I found the solution. It didn't work the first time because I was referencing the wrong object on when setting .State = EntityState.Detached;
here is the full corrected method that works as expected
private void PushToDelivery(IEnumerable<Mkl.WebTeam.UWManual.Model.Publication> recordsToPublish)
{
string recordEntity = string.Empty;
DbEntityEntry recordType = null;
// Loop through recordsToPublish and see if the record exists in Delivery. If so then 'Update' the record
// else 'Add' the record.
foreach (var record in recordsToPublish)
{
if (recordEntity != record.Entity)
{
recordType = PublishingFactory.DeliveryContext.Entry(ObjectExt.GetEntityOfType(record.Entity));
}
if (recordType == null)
{
continue;
////throw new NullReferenceException(
//// string.Format("Couldn't identify the object type stored in record.Entity : {0}", record.Entity));
}
// get the record from the Authoring context from the appropriate type table
object authoringRecordVersion = PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).Find(record.RecordId);
// get the record from the Delivery context from the appropriate type table
object deliveryRecordVersion = PublishingFactory.DeliveryContext.Set(recordType.Entity.GetType()).Find(record.RecordId);
// somthing happened and no records were found meeting the Id and Type from the Publication table in the
// authoring table
if (authoringRecordVersion == null)
{
continue;
}
if (deliveryRecordVersion != null)
{
// update record
PublishingFactory.DeliveryContext.Entry(deliveryRecordVersion).CurrentValues.SetValues(authoringRecordVersion);
PublishingFactory.DeliveryContext.Entry(deliveryRecordVersion).State = EntityState.Modified;
PublishingFactory.DeliveryContext.SaveChanges();
}
else
{
// insert new record
PublishingFactory.AuthoringContext.Entry(authoringRecordVersion).State = EntityState.Detached;
PublishingFactory.DeliveryContext.Entry(authoringRecordVersion).State = EntityState.Added;
PublishingFactory.DeliveryContext.SaveChanges();
}
recordEntity = record.Entity;
}
}
As you say in your comment the reason why you can't use .Single(a => a.ID == record.RecordId) is that the ID property is not known at design time. So what you can do is get the entity by the Find method and then detach it from the context:
PublishingFactory.AuthoringContext
.Entry(authoringRecordVersion).State = EntityState.Detached;

Orchard CMS- Get the current Data Migration Record version number

Given the name of a Migrations class as a string, how can I get the current version number as stored in Orchard_Framework_DataMigrationRecord?
I can see Version in IExtensionManager, but that appears to just be the module version as defined in module.txt.
OK, so I've solved this myself-
I knew that Orchard must already be executing similar code to what I require when it fires off migration methods, so I created a new migrations file, and put a breakpoint on the Create() method. When the breakpoint hit, I looked up through the call stack to find DataMigrationManager in Orchard.Data.Migration. Everything I needed was in there, and if anyone else has similar requirements, I suggest they have a look at that class as a starting point.
This is pretty much lifted straight out of that class:
string moduleName="Your.Module.Name";
var migrations = GetDataMigrations(moduleName);
// apply update methods to each migration class for the module
var current = 0;
foreach (var migration in migrations)
{
// copy the objet for the Linq query
var tempMigration = migration;
// get current version for this migration
var dataMigrationRecord = GetDataMigrationRecord(tempMigration);
if (dataMigrationRecord != null)
{
current = dataMigrationRecord.Version.Value;
}
// do we need to call Create() ?
if (current == 0)
{
// try to resolve a Create method
var createMethod = GetCreateMethod(migration);
if (createMethod != null)
{
//create method has been written, but not executed!
current = (int)createMethod.Invoke(migration, new object[0]);
}
}
}
Context.Output.WriteLine("Version: {0}", current);
A couple of methods you may need:
private DataMigrationRecord GetDataMigrationRecord(IDataMigration tempMigration)
{
return _dataMigrationRepository.Table
.Where(dm => dm.DataMigrationClass == tempMigration.GetType().FullName)
.FirstOrDefault();
}
private static MethodInfo GetCreateMethod(IDataMigration dataMigration)
{
var methodInfo = dataMigration.GetType().GetMethod("Create", BindingFlags.Public | BindingFlags.Instance);
if (methodInfo != null && methodInfo.ReturnType == typeof(int))
{
return methodInfo;
}
return null;
}
Don't forget to inject any dependencies that you may need.

Resources