Updating entity does not work in entity framework 6 - entity-framework

I have migrated my project from EF4 to EF6. I am facing trouble while updating the records. Below is my code
public int SaveApplicantData(Applicant objApplicant, bool isEdit)
{
DBEntities context = new DBEntities();
int applicantId = 0;
try
{
if (objApplicant.Id > 0)
{
var applicant = context.Applicants.Where(a => ((a.Id != objApplicant.Id) && (a.SSN == objApplicant.SSN))).FirstOrDefault();
if (applicant != null)
{
return -1;
}
else
{
applicant = context.Applicants.Find(objApplicant.Id);
}
if (applicant != null)
{
applicant.FirstName = "TEST NAME";
context.SaveChanges();
}
}
return objApplicant.Id;
}
}
I have also tried context.Entry(applicant).CurrentValues.SetValues(objApplicant) but does not work for me. Spending lot of hours in finding solution. Please assists with appropriate solution.
UPDATE
Also I tried
context.Applicants.Attach(objApplicant);
context.Entry(objApplicant).State = EntityState.Modified;
context.SaveChanges();
but no success!

Try the below code instead of adding in context.Applicants.Add(objApplicant);
context.Entry(objApplicant).State = EntityState.Modified;
context.SaveChanges();
Update: Try this code block.
if (applicant != null)
{
applicant.FirstName = "TEST NAME";
context.Entry(applicant).State = EntityState.Modified;
context.SaveChanges();
}

Related

EF Core Deleting Entities in Disconnected Environment

I'm having real difficulty with EF Core with a Web API project I'm working... to me EF Core is not intuitive at all. I'm in a disconnected environment and I'm trying to update Sudoku games. EF Core is spending more time deleting connections between users and their apps and roles than in updating the game. How do I disable delete statements in an update? There is no reason for deletes, I don't need them. How do I stop them?
The method is as follows, the game is loaded as a graph and my understanding is this code should change everything tracked to modified or added. To me it seems like EF Core is going out of it's way to delete things... this makes no sense. I never instructed it to delete anything:
async public Task<IRepositoryResponse> Update(TEntity entity)
{
var result = new RepositoryResponse();
try
{
dbSet.Update(entity);
context.ChangeTracker.TrackGraph(entity,
e => {
var dbEntry = (IEntityBase)e.Entry.Entity;
if (dbEntry.Id != 0)
{
e.Entry.State = EntityState.Modified;
}
else
{
e.Entry.State = EntityState.Added;
}
});
await context.SaveChangesAsync();
result.Success = true;
result.Object = entity;
return result;
}
catch (Exception exp)
{
result.Success = false;
result.Exception = exp;
return result;
}
}
Well, I found a work around but it is the equivalent to the fixing your bike with bubblegum and tape. It's ugly... but it works. Before I save the game I create a list of all associated apps and roles and then recreate and resave the values after await context.SaveChangesAsync();. The code is listed below:
async public Task<IRepositoryResponse> Update(TEntity entity)
{
var result = new RepositoryResponse();
try
{
entity.DateUpdated = DateTime.UtcNow;
context.Games.Update(entity);
context.ChangeTracker.TrackGraph(entity,
e => {
var dbEntry = (IEntityBase)e.Entry.Entity;
if (dbEntry.Id != 0)
{
e.Entry.State = EntityState.Modified;
}
else
{
e.Entry.State = EntityState.Added;
}
});
var apps = new List<App>();
var roles = new List<Role>();
foreach (var userApp in entity.User.Apps)
{
apps.Add(userApp.App);
}
foreach (var userRole in entity.User.Roles)
{
roles.Add(userRole.Role);
}
await context.SaveChangesAsync();
foreach (var app in apps)
{
userAppDbSet.Add(new UserApp(entity.UserId, app.Id));
}
foreach (var role in roles)
{
userRoleDbSet.Add(new UserRole(entity.UserId, role.Id));
}
await context.SaveChangesAsync();
result.Success = true;
result.Object = entity;
return result;
}
catch (Exception exp)
{
result.Success = false;
result.Exception = exp;
return result;
}
}
There has to be a better way of doing this? The full app can be found here, can someone tell me a better way of setting this up:
https://github.com/Joseph-Anthony-King/SudokuCollective

How to Repeat Previous Actions in Exception in EF 6

I am having a problem with repeating previous operations when there is an error in the SaveChanges method of Entity Framework.
Below is the code block
public static int SaveChangesTask(this DbContext db)
{
int result = -1;int countLoop = 0;
bool continueLoop = true;
var modifiedOrAddedEntities = db.ChangeTracker.Entries().Where(a => a.State != EntityState.Detached
&& a.State != EntityState.Unchanged).ToList();
while (continueLoop && countLoop<3)
{
try
{
result= db.SaveChanges();
continueLoop = false;
}
catch(Exception ex)
{
string error = ex.ToSystemException();
if(error.ToLowerInvariant().Contains("ORA-00060".ToLowerInvariant()) || error.ToLowerInvariant().Contains("deadlock"))
{
foreach (var item in modifiedOrAddedEntities)
{
db.Entry(item).State = item.State;
}
countLoop++;
Random rnd = new Random();
System.Threading.Thread.Sleep(rnd.Next(1, 5)* 1000);
}
else
{
throw ex;
}
}
}
return result;
}
But when I want to add old tracking objects to context, Entity Framework Throws Exception like that
"The entity type DbEntityEntry is not part of the model for the current context"

EF : related entities are set as INSERT instead of being only referenced to the added entity

I tried to find an answer through the related questions I got but I didn't see the same situation I have now. I a beginner with this framework.
The thing is that in the DB the TopicFeedbackType is always referred but TopicNavigatedUrl and Product are always inserted event if I attach the entity. What am I doing wrong? I attach the found entity to the correct entity set name. The entity gets attached. I noticed that before the p_TopicQuickFb have one of its property updated by an attached entity, its EntityKey is null, but when the currentNavUrl(for example) is set, the EntityKey of p_TopicQuickFb is not null anymore. Its value is "EntitySet=TopicQuickFeedbacks" but there is no id.
I am really lost in there.
public void AddTopicQuickFeedback(TopicQuickFeedback p_TopicQuickFb, string p_SessionID)
{
TopicFeedbackType currentType = this.GetTopicFeedbackType(p_TopicQuickFb.TopicFeedbackType.FeedbackType);
bool currentTypeAttached = false;
TopicNavigatedUrl currentNavUrl = this.GetTopicNavigatedUrl(p_TopicQuickFb.TopicNavigatedUrl.Url);
bool currentNavUrlAttached = false;
Product currentProduct = this.GetProduct(p_TopicQuickFb.Product.Name, p_TopicQuickFb.Product.MajorVersion, p_TopicQuickFb.Product.MinorVersion);
bool currentProductAttached = false;
using (COHFeedbackEntities context = GetObjectContext())
{
TopicFeedback tf = GetTopicFeedback(p_SessionID, context);
if (tf != null)
{
if (currentType != null)
{
p_TopicQuickFb.TopicFeedbackType = null;
context.AttachToOrGet<TopicFeedbackType>("TopicFeedbackTypes", ref currentType);
currentTypeAttached = true;
p_TopicQuickFb.TopicFeedbackType = currentType;
}
if (currentNavUrl != null)
{
p_TopicQuickFb.TopicNavigatedUrl = null;
context.AttachToOrGet<TopicNavigatedUrl>("TopicNavigatedUrls", ref currentNavUrl);
currentNavUrlAttached = true;
p_TopicQuickFb.TopicNavigatedUrl = currentNavUrl;
}
if (currentProduct != null)
{
p_TopicQuickFb.Product = null;
context.AttachToOrGet<Product>("Products", ref currentProduct);
currentProductAttached = true;
p_TopicQuickFb.Product = currentProduct;
}
tf.TopicQuickFeedbacks.Add(p_TopicQuickFb);
context.SaveChanges();
context.Detach(tf);
if (currentNavUrlAttached)
{
context.TopicNavigatedUrls.Detach(currentNavUrl);
}
if (currentProductAttached)
{
context.Products.Detach(currentProduct);
}
if (currentTypeAttached)
{
context.TopicFeedbackTypes.Detach(currentType);
}
}
}
}
I found the method in this post : Is is possible to check if an object is already attached to a data context in Entity Framework?
public static void AttachToOrGet<T>(this System.Data.Objects.ObjectContext context, string entitySetName, ref T entity)
where T : IEntityWithKey
{
System.Data.Objects.ObjectStateEntry entry;
// Track whether we need to perform an attach
bool attach = false;
if (
context.ObjectStateManager.TryGetObjectStateEntry
(
context.CreateEntityKey(entitySetName, entity),
out entry
)
)
{
// Re-attach if necessary
attach = entry.State == EntityState.Detached;
// Get the discovered entity to the ref
entity = (T)entry.Entity;
}
else
{
// Attach for the first time
attach = true;
}
if (attach)
{
context.AttachTo(entitySetName, entity);
}
}
Test method:
User user = new User(true, false, false);
string commentStr = "This is my comment";
Product product = new Product("ProductName", 7, 0);
TopicFeedbackComment commFeedback = new TopicFeedbackComment(commentStr, new TopicNavigatedUrl("http://testurl.com/test0"), product);
TopicFeedback feedback = new TopicFeedback(sessionID, user, FeedbackState.New);
provider.AddTopicFeedback(feedback);
TopicFeedback addedFeedback = provider.RetrieveTopicFeedback(sessionID);
provider.AddTopicFeedbackComment(commFeedback, sessionID);
Running this again and again do just INSERT to the
Can't post images so I can provide schema it if necessary.
My answer is in my last comment. I found it by myself.
If someone would like to comment why it's working this way it would be nice! :)

build index using lucene.net 2.9.2.2

I have to use lucene.net 2.9.2.2 with NHibernate 3.0. I have started to edit this old code:
public void BuildSearchIndex()
{
FSDirectory entityDirectory = null;
IndexWriter writer = null;
var entityType = typeof(MappedSequence);
var indexDirectory = new DirectoryInfo(GetIndexDirectory());
if (indexDirectory.Exists)
{
indexDirectory.Delete(true);
}
try
{
entityDirectory = FSDirectory.GetDirectory(Path.Combine(indexDirectory.FullName, entityType.Name), true);
writer = new IndexWriter(entityDirectory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), true, IndexWriter.MaxFieldLength.UNLIMITED);
}
finally
{
if (entityDirectory != null)
{
entityDirectory.Close();
}
if (writer != null)
{
writer.Close();
}
}
IFullTextSession fullTextSession = Search.CreateFullTextSession(this.Session);
// Iterate through Suppliers and add them to Lucene's index
foreach (MappedSequence instance in Session.CreateCriteria(typeof(MappedSequence)).List<MappedSequence>())
{
fullTextSession.Index(instance);
}
}
private string GetIndexDirectory()
{
INHSConfigCollection nhsConfigCollection = CfgHelper.LoadConfiguration();
string property = nhsConfigCollection.DefaultConfiguration.Properties["hibernate.search.default.indexBase"];
var fi = new FileInfo(property);
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fi.Name);
}
to build the index. The line:
FSDirectory.GetDirectory(Path.Combine(indexDirectory.FullName, entityType.Name), true);
still uses obsolete code. Could anyone be so kind and point out the necessary change. Thanks.
Christian
PS
Try using FSDirectory.Open(path) instead.

Entity Framework - Saving child entities on update

I have an Invoice entity and it has child InvoiceLog entities. When I first create an Invoice and add its InvoiceLog entities and save, it works fine. However, if I then edit the Invoice and try to add additional InvoiceLog entities, it completely ignores the new InvoiceLog entities and doesn't save them at all. Any ideas what I'm doing wrong?
//POST: /Secure/Invoices/Save/
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Save(Invoice invoice)
{
invoice.UpdateDate = DateTime.Now;
invoice.DeveloperID = Developer.DeveloperID;
invoice.InvoiceStatusID = (int)Enums.InvoiceStatus.Open;
if (invoice.InvoiceID == 0)
{//inserting new invoice.
DataContext.InvoiceData.Insert(invoice);
}
else
{//attaching existing invoice.
DataContext.InvoiceData.Attach(invoice);
}
AddHours(invoice);
//save changes.
DataContext.SaveChanges();
//redirect to invoice list.
return RedirectToAction("Index");
}
private void AddHours(Invoice invoice)
{
//get existing logs.
IQueryable<InvoiceLog> existingLogs = null;
if(invoice.InvoiceID > 0)
{
existingLogs = DataContext.InvoiceData.GetLogs(invoice.InvoiceID);
}
//create new logs.
var numDays = invoice.EndDate.Subtract(invoice.StartDate).TotalDays;
for (int k = 0; k <= numDays; k++)
{
//check if log already exists.
var existingLog = existingLogs.ToList().FindIndex(l => l.LogDate == invoice.StartDate.AddDays(k));
if (existingLog == -1)
{
//add new log.
var log = new InvoiceLog();
log.CreateDate = DateTime.Now;
log.UpdateDate = DateTime.Now;
log.Hours = 0;
log.InvoiceID = invoice.InvoiceID;
log.LogDate = invoice.StartDate.AddDays(k);
invoice.InvoiceLogs.Add(log);
}
}
}
Thanks,
Justin
You can try to add InvoiceLogs items before attaching the invoice:
else
{//attaching existing invoice.
AddHours(invoice);
DataContext.InvoiceData.Attach(invoice);
}