EntityState.Modified not working in Entity Code First - c#

I Use this code for update one field in my table.( with Entity Framework 6.1.3)
var model = new MyTable { Id = Id, UpdateTime = DateTime.UtcNow };
var dbSet = this.dbContext.Set<MyTable>();
dbSet.Attach(model);
entry = this.dbContext.Entry(model);
entry.State = EntityState.Modified;
this.dbContext.SaveChanges();
but this not work and UpdateTime does not change.and when i change code to this:
var model = this.dbContext.Set<MyTable>().Find(id);
model = new MyTable { Id = Id, UpdateTime = DateTime.UtcNow };
var dbSet = this.dbContext.Set<MyTable>();
entry = this.dbContext.Entry(model);
entry.State = EntityState.Modified;
this.dbContext.SaveChanges();
I found that in my first code , EF look to UpdateTime field that did not change, but is this right when i write:
entry.State = EntityState.Modified;
ef must generate update code , then why it does not?
How must i do for solve this problem?

Finally i found what's the problem?
I have a required string field in my table , and i found that we need to fill reference type fileds in Entity framework , and it can not be empty or whitespace character but not required the right value, and in this state we must don't use
entry.State = EntityState.Modified;
and instead of it we must use
entry.Property("UpdateTime").IsModified = true;
therefore this problem can be solved by this way:
var model = new MyTable { Id = Id, UpdateTime = DateTime.UtcNow , Title = "EveryThing" };
var dbSet = this.dbContext.Set<MyTable>();
dbSet.Attach(model);
entry = this.dbContext.Entry(model);
entry.Property("UpdateTime").IsModified = true;
this.dbContext.SaveChanges();

Related

Getting ID from entity that hasn't been saved yet

I have a scenario where I need to insert a record into a table - the myPerson Entity to get the personID (int identity). Then I need to take that personID and add it to the familyAdmin.personID.
I was hoping to do all of this in one db.SaveChange();
Is there a way to do it in one since the person entity is part of the userAdmin entity?
Currently how I have it set up:
userAdmin familyAdmin = new userAdmin();
familyAdmin.signupDate = DateTime.Today;
familyAdmin.lastLogin = DateTime.Today;
familyAdmin.registrationID = newReg.registrationID;
person myPerson = new person();
myPerson.personName = newReg.name;
myPerson.personEmail = newReg.email;
myPerson.personPhone = newReg.phone;
myPerson.personPhoneCarrier = newReg.carrierName;
myPerson.personDOB = newReg.dob;
myPerson.familyID = familyAdmin.familyID;
myPerson.personTypeID = newReg.personTypeID;
familyAdmin.personID = myPerson.personID;
familyAdmin.people.Add(myPerson);
db.userAdmins.Add(familyAdmin);
db.SaveChanges();
This option is currently not working. There is no error that is generated when I do this option. I just get a 0 instead of a 1,2,3 etc.
The insert into the person table is working and an ID is being generated correctly. It is just when I try to retrieve that ID to do the insert into the UserAdmin table at the same time that I get the 0.
Do I have to do something like this:
person myPerson = new person();
myPerson.personName = newReg.name;
myPerson.personEmail = newReg.email;
myPerson.personPhone = newReg.phone;
myPerson.personPhoneCarrier = newReg.carrierName;
myPerson.personDOB = newReg.dob;
myPerson.familyID = familyAdmin.familyID;
myPerson.personTypeID = newReg.personTypeID;
db.person.Add(myPerson);
db.SaveChanges();
userAdmin familyAdmin = new userAdmin();
familyAdmin.signupDate = DateTime.Today;
familyAdmin.lastLogin = DateTime.Today;
familyAdmin.registrationID = newReg.registrationID;
familyAdmin.personID = myPerson.personID;
db.userAdmins.Add(familyAdmin);
db.SaveChanges();
Partial EDMX image:
The first option is not working because of these two lines:
myPerson.familyID = familyAdmin.familyID;
familyAdmin.personID = myPerson.personID;
Those lines are not necessary because you're checking identifiers that are not created in the database.
Your code should look like this:
userAdmin familyAdmin = new userAdmin();
familyAdmin.signupDate = DateTime.Today;
familyAdmin.lastLogin = DateTime.Today;
familyAdmin.registrationID = newReg.registrationID;
person myPerson = new person();
myPerson.personName = newReg.name;
myPerson.personEmail = newReg.email;
myPerson.personPhone = newReg.phone;
myPerson.personPhoneCarrier = newReg.carrierName;
myPerson.personDOB = newReg.dob;
// myPerson.familyID = familyAdmin.familyID; Not necessary
myPerson.personTypeID = newReg.personTypeID;
// familyAdmin.personID = myPerson.personID; Not necessary
familyAdmin.people.Add(myPerson);
db.userAdmins.Add(familyAdmin);
db.SaveChanges();
If you have correctly configured the relation between people property on userAdmin entity and person entity so by using familyAdmin.people.Add(myPerson); and calling db.SaveChanges(); then EF will call DetectChanges internally so that will fix the relationship between those two entities and generate the correct SQL in the correct order because it knows which entity need to be inserted first and which entity need the foreign key id.

Entity Framework 6 Add/Update - Error while edit and try to add edited entity as new one

I have a model like below
public class XYZModel
{
public string Id; // GUID, primary key;
public string Name;
public string AssociationId; // GUID, AllowNull;
}
what I am doing..
This is working fine
XYZModel abc = new XYZModel();
abc.Id = Convert.ToString(Guid.NewGuid());
abc.Name = "ABC Name";
xyzDbContext.XYZModels.Add(abc);
xyzDbContext.SaveChanges();
What is my goal ? Get entity by id, Edit it, Change its primary key Id value, and add it as a new entry. but error occurred while adding.
XYZModel xyz = xyzDbContext.XYZModels.Find("xyzguid");
//modifying it
xyz.AssociationId = xyz.Id;
xyz.Id = Convert.ToString(Guid.NewGuid());
xyz.Name = "New Name";
//trying to add it as new entry
xyzDbContext.XYZModels.Add(xyz);// Error
xyzDbContext.SaveChanges();
It throw an error
The property 'Id' is part of the object's key information and cannot be modified.
You can do that only if the xyz object is detached from Context.
Two ways to do that:
XYZModel xyz = xyzDbContext.XYZModels.Find("xyzguid");
xyzDbContext.Entry(xyz).State = EntityState.Detached;
Or using AsNoTracking.FirstOrDefault
XYZModel xyz = xyzDbContext.XYZModels.AsNoTracking().FirstOrDefault(s => s.Id =="xyzguid");
Your code with first approach:
XYZModel xyz = xyzDbContext.XYZModels.Find("xyzguid");
xyzDbContext.Entry(xyz).State = EntityState.Detached;
//modifying it
xyz.AssociationId = xyz.Id;
xyz.Id = Convert.ToString(Guid.NewGuid());
xyz.Name = "New Name";
//trying to add it as new entry
xyzDbContext.XYZModels.Add(xyz);// No Error
xyzDbContext.SaveChanges();
Note:
You must use DatabaseGeneratedOption.None annotation on Id property.
Entity Framework tracks objects as you edit them. If you want a new row inserted into the database, create a new object in memory with the values you want and add that. A library like AutoMapper might come in handy here.

Error add object in table contaning FK

I create tow table in sql server 2008 with relationship 1 - * .
table 1: Tour (ID, date, ..) : ID : PK
table 2 : Position (ID,..) : ID : PK, and TourID : FK
Tour tour = new Tour() { ID = 17 /* this ID exist in table tou*/};
Position position = new Position();
position.Tour = tour;
position.Longitude = Longitude;
position.DateHeurePosition = DateH;
db.AttachTo("Tour", tour);
db.AddToPosition(position);
db.SaveChanges();
this error is displayed:
An object with the same key already exists in the ObjectStateManager.
The ObjectStateManager cannot track multiple objects with the same key
How to resolve this error?
In order to resolve this error, you need to make sure that the id that you are adding is unique.
What you did is that you created a new Tour with an ID that already exists.
In case you want to attach the position to the tour having ID=17, you have to get the record you want from the database:
Replace position.Tour = tour;
with position.Tour = db.Tour.FirstOrDefault(p=>p.ID==17);
You can solve this by detaching it first, there are some things you can do to Update the object by just setting the new values. Like this:
ObjectContext API: context.YourEntitySet.ApplyCurrentValues(newEntity);
DbContext API: context.Entry(oldEntity).CurrentValues.SetValues(newEntity);
I think the only thing you need here, is to find the attached item something like below
Tour t = Tours.Find(Id);//e.g. Id = 17 where Tours is the DbContext.Set<Tour>
position.Tour = t;
If you have another list of tours:
Tour t = Tours.First(i=> i.Id == Id);//e.g. Id = 17 where Tours is something with interface IEnumarable<Tour>
position.Tour = t;
And then set the values to the rest of that item.
But if you want to see a more complex implementation of update, here is my implementation of the update method:
public virtual void Update(T entity)
{
DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
var attachedEntity = DbSet.Find(entity.Id);
if (attachedEntity != null)
{
var attachedEntry = DbContext.Entry(attachedEntity);
entity.Created = attachedEntity.Created;
entity.LastModified = DateTime.Now;
attachedEntry.CurrentValues.SetValues(entity);
}
else
{
dbEntityEntry.State = EntityState.Modified;
entity.LastModified = DateTime.Now;
}
}
When you adjust it to your needs, you can pass the object to the method and then save the changes.

Entity Framework 4 - Duplicate Key Upon Update

I'm having trouble performing an update in the Entity Framework. I don't really understand the behaviour I am seeing.
I am using the AdventureWorks database.
The starting value for the StateProvince is Micronesia. If I change it to Maryland, the update is successful. However, if I then try to change it back to Micronesia, I get the following error:
"Cannot insert duplicate key row in object 'Sales.SalesTerritory' with
unique index 'AK_SalesTerritory_Name'.\r\nThe statement has been
terminated."
The DAL method in question is:
public static void UpdateCustomer(CustomerDetails customerDetails)
{
AWEntities context = Common.GetContext();
var customerQuery = from c in context.Individuals
.Include("Contact")
.Include("Customer.CustomerAddresses.Address.StateProvince.SalesTerritory")
//.Include("Customer.SalesTerritory.StateProvinces")
.Where(id => id.CustomerID == customerDetails.CustomerId)
select c;
var individual = customerQuery.ToList().ElementAt(0);
Contact contact = individual.Contact;
contact.LastName = customerDetails.LastName;
contact.MiddleName = customerDetails.MiddleName;
contact.FirstName = customerDetails.FirstName;
contact.EmailAddress = customerDetails.EmailAddress;
contact.Phone = customerDetails.Phone;
contact.Title = customerDetails.Title;
AWModel.Customer customer = individual.Customer;
customer.CustomerID = customerDetails.CustomerId;
customer.SalesTerritory.Name = customerDetails.SalesTerritory;
Address address = individual.Customer.CustomerAddresses.ElementAt(0).Address;
address.AddressLine1 = customerDetails.AddressLine1;
address.AddressLine2 = customerDetails.AddressLine2;
address.City = customerDetails.City;
address.PostalCode = customerDetails.PostalCode;
address.StateProvinceID = customerDetails.SalesProvinceId;
context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
}
Can anyone identify the correct way to do what I am attempting.
This is occurring when you update the SalesTerritory.Name property:
customer.SalesTerritory.Name = customerDetails.SalesTerritory;
The effect is to change the SalesTerritory entity, rather than the customer entity. I believe you want something more like:
customer.SalesTerritoryID = customerDetails.SalesTerritoryID;

Entity DB Adding New User and Other Related Data to DB

Hey. Nooby question but new with Entity.
I am trying to create a new user object and some details in some additional tables which have a foreign key of the newly created user id.
I've attempted to do this in one round trip. Do I have to add the user to the database first and then go back, set the userid's on the other objects and add them. Here is the Entity Model and code to elaborate:
using (var context = new ServicesEntities())
{
newUser = new UsersTable();
newUser.Address = user.UserDetails.Address;
newUser.City = user.UserDetails.City;
newUser.Country = user.UserDetails.Country;
newUser.Email = user.Email.EmailString;
newUser.FirstName = user.UserDetails.FirstName;
newUser.LastName = user.UserDetails.LastName;
newUser.State = user.UserDetails.State;
newUser.Zip = user.UserDetails.Zip;
context.UsersTables.AddObject(newUser);
context.SaveChanges();
}
using (var context = new ServicesEntities())
{
var referralDetails = new UserReferrals();
referralDetails.CreatedThruServiceId = 1; // todo don't make this an absolute 1
referralDetails.ReferralEmail = user.ReferralDetails.ReferralEmail;
referralDetails.TwoPlusTwoHandle = user.ReferralDetails.TwoPlusTwoHandle;
referralDetails.UserId = newUser.UserId;
context.UserReferrals.AddObject(referralDetails);
context.SaveChanges(); // THIS WORKS FINE!
}
using (var context = new ServicesEntities())
{
var credentials = new UserCredentials();
credentials.CreatedOn = DateTime.Now;
credentials.EmailValidated = false;
//credentials.EmailValidatedOn = null;
credentials.FailedLoginAttempts = 0;
credentials.IsLockedOut = false;
//credentials.LastValidLogin = null;
credentials.Password = user.Password.PasswordString;
credentials.PermissionId = 1; // todo don't make this an absolute 1 = user
credentials.SuccessfulLoginAttempts = 0;
credentials.UserId = newUser.UserId; ;
context.UserCredentials.AddObject(credentials);
context.SaveChanges(); // THIS ONE CRAPS OUT!
}
When I run this I get the following Exception when I run SaveChanges():
{"A dependent property in a
ReferentialConstraint is mapped to a
store-generated column. Column:
'UserId'."}
Note: Updated this with some slightly different code based on an example in a book.
Note2: I've narrowed down the problem to be in the adding of credentials.
Note3: Fixed this, I accidentally had AUTO-INCREMENT set on my UserCredentials userid. If anyone ares here is working code:
public POCO.User AddNewUserToDb(User user)
{
if (IsDuplicateUser(user.Email.EmailString))
{
throw new DuplicateNameException("This email is already taken.");
}
UsersTable newUser;
using (var context = new ServicesEntities())
{
newUser = new UsersTable();
newUser.Address = user.UserDetails.Address;
newUser.City = user.UserDetails.City;
newUser.Country = user.UserDetails.Country;
newUser.Email = user.Email.EmailString;
newUser.FirstName = user.UserDetails.FirstName;
newUser.LastName = user.UserDetails.LastName;
newUser.State = user.UserDetails.State;
newUser.Zip = user.UserDetails.Zip;
var referralDetails = new UserReferrals();
referralDetails.CreatedThruServiceId = 1; // todo don't make this an absolute 1
referralDetails.ReferralEmail = user.ReferralDetails.ReferralEmail;
referralDetails.TwoPlusTwoHandle = user.ReferralDetails.TwoPlusTwoHandle;
//referralDetails.UserId = newUser.UserId;
var credentials = new UserCredentials();
credentials.CreatedOn = DateTime.Now;
credentials.EmailValidated = false;
//credentials.EmailValidatedOn = null;
credentials.FailedLoginAttempts = 0;
credentials.IsLockedOut = false;
//credentials.LastValidLogin = null;
credentials.Password = user.Password.PasswordString;
credentials.PermissionId = 1; // todo don't make this an absolute 1 = user
credentials.SuccessfulLoginAttempts = 0;
//credentials.UserId = newUser.UserId; ;
newUser.Credentials = credentials;
newUser.ReferralDetails = referralDetails;
context.UsersTables.AddObject(newUser);
context.SaveChanges();
}
user.UserId = newUser.UserId;
return user;
Try to add related records directly to UserTable record:
newUser.Credentials.Add(credentials);
newUser.ReferralDetails.Add(referralDetails);
Do not set any Id. It will be set during saving automatically.
Edit: Btw. make sure that UserId column in UserCredentials table is not set as auto generated in database.
Take a look at these links:
Using the entity framework to add existing entities to a collection on a newly created entity.
How to create foreign key relationships with the Entity Framework?
Entity Framework - insert new object with a collection of existing objects
The key links for EF4:
Fortunately, in EF4 we can directly
update the relationship due to the
Foreign Key Association which allows
us to keep the foreign key property
inside the entity classes. For
detail, please see
http://blogs.msdn.com/adonet/archive/2009/11/06/foreign-key-relationships-in-the-entity-framework.aspx.
Besides, we have another great feature
Self Tracing Entities, which makes the
n-tier pattern much easier in EF,
http://blogs.msdn.com/adonet/archive/2009/11/15/updated-feature-ctp-walkthrough-self-tracking-entities-for-the-entity-framework.aspx.
EF4 will allow you to include the foreign key values as scalar properties of your entities. Make sure the "Include foreign keys" checkbox is checked when you create your EDM.
Looking at your model, it looks like you've already done that. Just set the foreign key values explicitly, no need to do a round trip.

Categories

Resources