I have an entity named: Application and it has field ApplicationStatus which is entity as well, ApplicationStatus values are yes or no and it's nullable in Application.
So when I execute:
Application application = MyEntities.Applications.First();
application.ApplicationStatus = null;
MyEntities.SaveChanges();
ApplicationStatus won't update its value, unless I debug it and do quick watch application.ApplicationStatus.
However
application.ApplicationStatusId = null;
works fine.
My question, why this one doesn't work:
application.ApplicationStatus = null;
Thanks
EDIT further question:
As #LadislavMrnka answer solves debug behaviour and and the issue related lazy loading:
how can we interpret these situation?
Application application = MyEntities.Applications.First();
application.ApplicationStatusId = null; //This updates value in db
ApplicationStatus applicationStatus = MyEntities.ApplicationStatuses.First(a => a.Name == "no");
app.ApplicationStatus = applicationStatus; //This updates value in db too
app.ApplicationStatus = null; // But this doesn't
Use this and it will work:
Application application = MyEntities.Applications.Include("ApplicationStatus").First();
The reason is that your ApplicationStatus was never loaded. If you do debug and access it your debugging access will trigger lazy loading and loads it.
Related
I upgrade from Play 2.5 to 2.7, and am having a problem with saving my forms.
When fields are changed and I call the Model.update() the changes are not persisted in the database (even though they show changed when debugging before the update is done)
When however I set them specifically, then they do persists. So it must have to do something with the fact that it does not detect the change and does not see the object as changed. I use getter and setters in the model, and all the properties are private.
This is the controller function (with the two lines to persist those two fields)
#Check(UserTask.MANAGER)
public Result updateSceneSet(Http.Request request) {
Messages messages = messagesApi.preferred(request);
Form<StreamingSceneSet> form = formFactory.form(StreamingSceneSet.class).bindFromRequest(request);
if (form.hasErrors()) {
if (form.rawData().get("id") != null && form.rawData().get("id").length() > 0) {
long itemId = Long.parseLong(form.rawData().get("id"));
StreamingSceneSet item = StreamingSceneSet.findById(itemId);
return badRequest(views.html.streaming.editSceneSetView.render(form, item, messages, request));
} else {
return badRequest(views.html.streaming.createSceneSetView.render(form,messages, request));
}
}
// Form is OK, has no errors we can proceed
StreamingSceneSet item = form.get();
item.setName(item.getName());
item.setDescription(item.getDescription());
// Insert or update?
if (item.getId() == null) {
item.insert();
flash("success", messages().at("addedSceneSet", item.getName()));
} else {
item.update();
flash("success", messages().at("updatedSceneSet", item.getName()));
}
return redirect(routes.Streaming.sceneSets());
}
It seems because when I started the upgrade I had some legacy classes I didn't have getters and setters, and as I had some issue I put in:
play.forms.binding.directFieldAccess = true
Removing this made everything work again.
I think I am missing something in my understanding of tracking property value changes in entity framework.
I have an application where i store service requests. Whenever a team value in changed in the service request record, I want to create a team history record in a related teamhistory entity.
I have created the app in MVC using the standard scaffolding for controllers and views.
In the (post)edit task in the controller, the standard logic generated has the following code
if (ModelState.IsValid)
{
db.Entry(serviceRequest).State = EntityState.Modified;
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(serviceRequest);
I have modified that to include the creating of the teamhistory record and an individualhistory record for individual assigned within team. The code for creating these related records work, BUT i want these records only created when the values on team or member(individual) change from what they were previously.
So far the conditions i have specified due not trigger this correctly because I havent gotten the condition right. Below is the current code:
//string teamorig = db.Entry(serviceRequest).Property(u => u.Team).OriginalValue.ToString();
//string teamcurr = db.Entry(serviceRequest).Property(u => u.Team).CurrentValue.ToString();
//if (teamorig != teamcurr)
var TeamIsModified = db.Entry(serviceRequest).Property(u => u.Team).IsModified;
if (TeamIsModified)
{
serviceRequest.TeamAssignmentHistories.Add(new TeamAssignmentHistory()
{
DateAssigned = DateTime.Now,
AssignedBy = User.Identity.Name,
ServiceRequest = serviceRequest.Id,
Team = serviceRequest.Team
});
}
//=========================================================================================
// if individual assigned has changed add individual history record========================
var IndividualIsModified = db.Entry(serviceRequest).Property(u => u.Member).IsModified;
if (IndividualIsModified)
{
serviceRequest.IndividualAssignmentHistories.Add(new IndividualAssignmentHistory()
{
DateAssigned = DateTime.Now,
AssignedBy = User.Identity.Name,
ServiceRequest = serviceRequest.Id,
AssignedTo = serviceRequest.Member.Value,
});
}
//===========================================================================================
The var teamismodified logic doesnt work. When I save the page without making any changes on it- the logic kicks off because in debugging it thinks the field has been modified.
When I comment out that code and uncomment the code above it for original and currentvalues- ie the teamorig and teamcurr logic, teamcurr and teamorig have the same values in debug, even when they have been forced into a change on the save in the MVC view page. Because they have the same values, the if condition is false so the team history record is not created.
The above code has been sandwiched in between
db.Entry(serviceRequest).State = EntityState.Modified;
and
await db.SaveChangesAsync();
statements.
What am I not understanding about entity framework tracking changes in mvc? Why does think its modified when i make not changes to team, and why are teamorig and teamcurr the same when I do make the changes?
Any advice would be welcome. Thanks
We're on CRM 2013 on-premise. I'm writing a plugin that fires when a field on Quote entity is updated.
So I registered my plugin on 'Update' message. Then the event is 'Post-operation'. (I tried Pre-operation but still no luck)
Basically the goal is when the field is updated, create a new entity 'ContractShell' and then create relationship between the Quote and the newly created 'ContractShell'.
However my problem is when the field is updated, my plugin never seems to fire. I just simply put a InvalidPluginExecutionException in my code, but for some reason it never fires.... Any ideas? Thanks.
Here's a screenshot of my plugin step:
Here's my code:
var trace = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
// The InputParameters collection contains all the data passed in the message request.
var targetEntity = context.GetParameterCollection<Entity>(context.InputParameters, "Target");
if (targetEntity == null)
throw new InvalidPluginExecutionException(OperationStatus.Failed, "Target Entity cannot be null");
if (!context.OutputParameters.Contains("id"))
return;
Guid QuoteId = (Guid)targetEntity.Attributes["quoteid"];
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = serviceFactory.CreateOrganizationService(context.UserId);
var contractShellEntity = new Entity();
contractShellEntity = new Entity("new_);
//assign the portfolio
if (targetEntity.Attributes.Contains(Schema.Quote.Portfolio))
{
var quotePortfolio = (EntityReference)targetEntity.Attributes[Schema.Quote.Portfolio];
contractShellEntity[Schema.new_ContractShell.PortfolioName] = new EntityReference(quotePortfolio.LogicalName, quotePortfolio.Id);
}
var contractShellId = service.Create(contractShellEntity);
throw new InvalidPluginExecutionException(OperationStatus.Failed, "I created New Contract Shell");
//Creating relationship between Contract Shell and the newly created Accounts
var quoteContractReferenceCollection = new EntityReferenceCollection();
var quoteContractRelatedEntity = new EntityReference
{
Id = contractShellId,
LogicalName = contractShellEntity.LogicalName
};
quoteContractReferenceCollection.Add(quoteContractRelatedEntity);
var quoteContractReferenceCollectionRelRelationship = new Relationship
{
SchemaName = Schema.new_ContractShell.ContractQuoteRelationship
};
service.Associate("quote", QuoteId, quoteContractReferenceCollectionRelRelationship, quoteContractReferenceCollection);
You need to register not only the plugin but an SDKMessageProcessingStep. Also, you have to implement the Execute method in your plugin to be able to register it, so either you're missing code in your snippet, or your code is the problem.
Also, your InvalidPluginExecutionException is nested after a number of checks. Theres a good chance you don't have any output parameters if you don't know how to register a plugin, so your code would actually return before you hit the exception.
I have been reading all similar posts I found regarding EF but I can't still manage to found a solution.
I'm very new to the EF and I have been reading some useful info about working with it but I think that I'm missing something.
The scenario is like this:
I want a user to be able to create an account in an ASP.NET webpage. So I have a table named 'Accounts'. The user must agree with the condition terms of the site, that may be updated in the futere, so I have also a table called 'ConditionTerms' that has 1 to many relation with the account (many accounts have an unique condition term).
I wanted to separete the specific personal user data from the data of the account so I also created a table called 'Persons' and I set the relation ship so that a person may have many accounts.
Now, when I want to save an account into the database, I retrieve the last conditionTerm available in the database and I attach it to the account entity. Then when I try to save the data via SaveChanges() I get the exception mentioned in the title of the post. The thing is that if all entities are new, when the associations are created, the EntityState for all the items is 'Detached' and it works, but when I retrieve the existing conditionTerm from the data base and I add it to the account.ConditionTerm, the account changes its state to 'Added' and then it throws the exception.
I read somewhere that when this happens, it means that all the entity tree is considered as already added by the context and I should only need to call SaveChanges() without the AddObject() method since it is already added. I tried this and then I get no exception and the code ends, but then if I check the database (SQL Server 2008 express) the account hasn't been added at all.
This is the code I'm trying and I think it should work but it's clear that I'm missing something:
[TestMethod]
public void TestCreateNewAccount()
{
try
{
AccountRepository accountRepository = new AccountRepository();
Account account = new Account()
{
Username = "TestUsername",
Password = "TestPassword",
Email = "TestEmail",
Nickname = "TestNickName",
Quote = "Test Quote",
AgreedToTermsDate = DateTime.Now,
CreationDate = DateTime.Now,
LastUpdateTime = DateTime.Now
};
// This works (all new entities!)
//ConditionTerm conditionTerm = new ConditionTerm()
//{
// Text = "This is some test condition term.",
// CreationDate = DateTime.Now,
// LastUpdateTime = DateTime.Now
//};
//This does not work (attaching an existing entity to a new one)
ConditionTerm conditionTerm = new ConditionTermsRepository().GetCurrentTerm();
Person person = new Person()
{
FirstName = "TestName",
Surname = "TestSurname",
CreationDate = DateTime.Now,
LastUpdateTime = DateTime.Now
};
account.ConditionTerm = conditionTerm;
account.Person = person;
using (ImproveEntities entities = Connection.GetModel())
{
if (account.ID > 0)
{
Account newAccount = new Account();
newAccount.ID = account.ID;
entities.Accounts.Attach(newAccount);
entities.Accounts.ApplyCurrentValues(account);
}
else
{
entities.Accounts.AddObject(account);
entities.SaveChanges();
}
}
}
catch (Exception)
{
}
}
Any help would be very much apreciated!
EDIT: This is the GetCurrentTerm() method:
public ConditionTerm GetCurrentTerm()
{
using (ImproveEntities entities = Connection.GetModel())
{
ConditionTerm conditionTerm = (from ct in entities.ConditionTerms
orderby ct.CreationDate descending
select ct).FirstOrDefault();
return conditionTerm;
}
}
If I understand correctly you want to insert a new account along with a new user into the database. But you don't want to create a new ConditionTerm but instead assign an existing ConditionTerm to the account.
The problem is that you fetch the existing ConditionTerm in another context (in your GetCurrentTerm) than the context you use for saving the new account. This second context doesn't know anything about the ConditionTerm, so you must EF explicitely tell that this conditionTerm already exists by attaching it to the second context:
// ...
using (ImproveEntities entities = Connection.GetModel())
{
entities.ConditionTerms.Attach(conditionTerm);
account.ConditionTerm = conditionTerm;
account.Person = person;
entities.Accounts.AddObject(account);
entities.SaveChanges();
}
// ...
I can't figure out why calling SaveChanges() on the following code results in no changes to the objects I attached:
public void Update()
{
AccountUser accountUser = new AccountUser();
// update
using (var db = new MedicalSystemDBEntity())
{
var query = from user in db.AccountUsers
where user.id == this.UserID
select user;
if (query.Count() > 0)
{
accountUser = query.First();
accountUser.AccountRoles.Load();
accountUser.SecurityNavigationNodes.Load();
// delete existing user roles before re-attaching
if (accountUser.AccountRoles.Count > 0)
{
foreach (AccountRole role in accountUser.AccountRoles.ToList())
{
accountUser.AccountRoles.Remove(role);
}
}
db.SaveChanges();
// get roles to add
List<int> roleIDs = new List<int>();
foreach (UserRole r in this.AccountRoles)
{
roleIDs.Add(r.RoleID);
}
var roleEntities = from roles in db.AccountRoles
where roleIDs.Contains(roles.id)
select roles;
accountUser.AccountRoles.Attach(roleEntities);
accountUser.username = this.Username;
accountUser.firstname = this.FirstName;
accountUser.middlename = this.MiddleName;
accountUser.lastname = this.LastName;
accountUser.enabled = this.Enabled;
if (this.LastActivityDate != null || this.LastActivityDate != DateTime.MinValue)
accountUser.lastactivitydate = this.LastActivityDate;
db.SaveChanges();
}
}
}
In the debugger, I see that the correct roleEntities are being loaded, and that they are valid objects. However, if I use SQL Profiler I see no UPDATE or INSERT queries coming in, and as a result none of my attached objects are being saved.
They're not saving because you change the entities before attaching them. Changes are tracked by the context (usually), so changes to detached entities aren't tracked. Hence, nothing to save.
Off the top of my head, shouldn't you do SaveChanges() after you've removed the roles from the account? Aren't you just removing the roles attached to the user, then reattaching the same ones? Since its saving the changes, nothing would have changed would it?
Sometimees its because the entit objects were modified while detached. The post here will show how to clear that up.