I am trying to add existing users to my Recipients collection in my MVC controllers CreateMessage action which passes a CreateMessageViewModel which should populate my domain Message object.
public class CreateMessageViewModel
{
public string Body { get; set; }
public ICollection<int> Recipients { get; set; }
}
Recipients are the posted user ID's I've selected in my view and the body is the message body.
My domain object is as follows:
public partial class Message : ModelBase
{
public Message() {
this.Recipients = new HashSet<User>();
}
[Key]
public int Id { get; set; }
public int SenderId { get; set; }
[ForeignKey("SenderId")]
public virtual User Sender { get; set; }
public virtual ICollection<User> Recipients { get; set; }
public string Body { get; set; }
}
My controller action and respository is as follows:
UnitOfWork db = new UnitOfWork();
[HttpPost]
public ActionResult Create(Model.ViewModel.CreateMessageViewModel messagevm)
{
if (ModelState.IsValid)
{
var CurrentUserId = WebSecurity.CurrentUserId;
MessageNotification message = new MessageNotification();
message.Message = new Message
{
Body = messagevm.Body,
SenderId = CurrentUserId
};
foreach (int userId in messagevm.Recipients)
{
// How do I add the existing recipients here?
// I get an exception here if I run this code and then save...
User recipient = new User { UserId = userId };
db.UserRepository.Attach(recipient);
message.Message.Recipients.Add(recipient);
}
message.Sent = DateTime.Now;
message.UserId = CurrentUserId;
db.MessagingRepository.Add(message);
db.Save();
return RedirectToAction("Index");
}
return View(messagevm);
}
public class Repository<TEntity> : IDisposable where TEntity : class
{
internal MyDB Context;
internal DbSet<TEntity> dbSet;
public Repository(MyDB context)
{
this.Context = context;
this.dbSet = Context.Set<TEntity>();
}
public virtual void Attach(TEntity entityToAttach)
{
dbSet.Attach(entityToAttach);
}
............
}
How do I attach the user entities to the Recipients collection without fetching them from the database? I am using the same implementation of the repository pattern as stated in the ASP.NET MVC tutorials .
With the code above I get the following exception:
Store update, insert, or delete statement affected an unexpected
number of rows (0). Entities may have been modified or deleted since
entities were loaded. Refresh ObjectStateManager entries
You can do
var user = new User { UserId = userId };
db.Users.Attach(user);
message.Message.Recipients.Add(user);
You may want to check whether the user is already loaded in the context:
var user = db.Users.Local.FirstOrDefault(u => u.UserId == userId);
if (user == null)
... // create and attach user as above.
Edit
Your modification made me notice that db is not a context, but a unit of work. You could wrap the logic above in a method in db.MessagingRepository, like GetUser(int userId).
Related
I am trying to build a three tier architecture with BLL, DAL, and UI. I am working on a small Apartment Management System project (which includes the information about resident students, their rooms and the apartment of the rooms they stay). Since I am a beginner I have some technical problems I need to solve. I am using Entity Framework with repository pattern. My project is based on MVVM approach and I am using Automapper.
Codes for Automapper
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
CreateMap<Room, RoomViewModel>().ReverseMap();
CreateMap<Apartment, ApartmentViewModel>().ReverseMap();
}
}
public class AutoMapperConfig
{
public static void Configure()
{
Mapper.Initialize(x =>
{
x.AddProfile<AutoMapperProfile>();
});
}
}
I am trying to add a new room to my database. There is a many-to-many relationship between my Room and Apartment tables and my database looks like this:
My Database's screen shot
My IRepository interface looks like:
public interface IRepository<T> where T : class
{
IEnumerable<T> GetAll();
T GetById(int id);
T Get(Expression<Func<T, bool>> expression);
IQueryable<T> GetMany(Expression<Func<T, bool>> expression);
bool Insert(T obj);
bool Update(T obj);
bool Delete(int id);
int Count();
void Save();
}
I have RoomRepository and ApartmentRepository, both implement IRepository interface. I have created my repositories and infrastructures:
Infrastructure (folder)
IApartmentRepository.cs
IRepository.cs
IRoomRepository.cs
IStudentRepository.cs
IUserRepository.cs
Repository (folder)
ApartmentRepository.cs
RoomRepository.cs
StudentRepository.cs
UserRepository.cs
While adding a new Room, admin has to state to which apartment that room belongs. The Add method inside the RoomController is below:
[HttpPost]
public JsonResult Add(RoomViewModel roomModel)
{
try
{
//var apartViewModel = new ApartmentRoomViewModel();
//apartViewModel.ApartmentID = roomModel.ApartmentNameId;
var room = AutoMapper.Mapper.Map<Room>(roomModel);
var status = _roomRepository.Insert(room);
_roomRepository.Save();
//apartViewModel.RoomID = room.Id;
return Json(new { status, message = "Ekleme işlemi başarılı." }, JsonRequestBehavior.AllowGet);
}
catch (Exception)
{
return Json(new { status = false, message = "Hata! Ekleme işlemi gerçekleştirilemedi." }, JsonRequestBehavior.AllowGet);
}
}
RoomViewModel
public class RoomViewModel
{
public int Id { get; set; }
public int DoorNumber { get; set; }
public int FloorNumber { get; set; }
public int Capacity { get; set; }
public int Fullness { get; set; }
public string ApartmentName { get; set; }
public int ApartmentNameId { get; set; }
}
UI
Room Add UI
My question is, when I want to insert the data I take from the user in the Room Add page, I can add the information gathered for the room to the Room table but I also want to add the apartment information (which is the ApartmentID of that apartment) of that room and the same room's RoomID to the ApartmentRoom table in the database and I couldn’t do that so far. If I’m not wrong so far, in that case what should I do?
Should I create another repository like ApartmentRoomRepository implementing IRepository interface and call the insert method of ApartmentRoomRepository in the Add method inside the RoomController? (This approach doesn’t seem like a correct one, as far as I understand but I’m not sure.)
Instead of the first option, should I create ApartmentRoomViewModel? In this case, how can I insert ApartmentID of the room with the room's RoomID to the ApartmentRoom table?
EDIT 1: I am using Database First approach.
EDIT 2: I have found the solution and shared as an answer below.
I've never used the automapper feature, and have separate model and viewmodel objects, but in this scenario I would create a new ApartmentRoom object as well as the new Room object, save them both to the database. The ApartmentRoom model that was created is where the linking information is stored. EF is not very obvious for many-to-many relationships.
If you sure you handle the domain classes and fluent API also I presume it is not EF core you playing with. You can get Apartment from ApartmentRepository then add it to the room apartments and add it to database.
[HttpPost]
public JsonResult Add(RoomViewModel roomModel)
{
try
{
//var apartViewModel = new ApartmentRoomViewModel();
//apartViewModel.ApartmentID = roomModel.ApartmentNameId;
var room = AutoMapper.Mapper.Map<Room>(roomModel);
var apart= apartmentRepository.GetById(roomModel.ApartmentNameId);
room.Apartments.Add(apart);
var status = _roomRepository.Insert(room);
_roomRepository.Save();
//apartViewModel.RoomID = room.Id;
return Json(new { status, message = "Ekleme işlemi başarılı." }, JsonRequestBehavior.AllowGet);
}
catch (Exception)
{
return Json(new { status = false, message = "Hata! Ekleme işlemi gerçekleştirilemedi." }, JsonRequestBehavior.AllowGet);
}
}
I have managed to find the solution. Firstly, I have added a single line to my AutoMapperProfile.cs file.
AutoMapperProfile.cs
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
CreateMap<Room, RoomViewModel>().ReverseMap();
CreateMap<Apartment, ApartmentViewModel>().ReverseMap();
// Added this new line
CreateMap<ApartmentRoom, ApartmentRoomViewModel>().ReverseMap();
}
}
public class AutoMapperConfig
{
public static void Configure()
{
Mapper.Initialize(x =>
{
x.AddProfile<AutoMapperProfile>();
});
}
}
ApartmentRoom.cs
This class is already generated from my database.
public partial class ApartmentRoom
{
public int Id { get; set; }
public int ApartmentID { get; set; }
public int RoomID { get; set; }
public virtual Apartment Apartment { get; set; }
public virtual Room Room { get; set; }
}
ApartmentRoomViewModel.cs
I have created this class.
public class ApartmentRoomViewModel
{
public int ApartmentID { get; set; }
public int RoomID { get; set; }
}
RoomController
I have changed the inside of RoomController a little. I have created an _entities object to be able to insert data into ApartmentRoom table.
public class RoomController : Controller
{
ApartmentManSysEntities _entities = new ApartmentManSysEntities();
private readonly IRoomRepository _roomRepository;
private readonly IApartmentRepository _apartmentRepository;
public RoomController(IRoomRepository roomRepository, IApartmentRepository apartmentRepository)
{
_roomRepository = roomRepository;
_apartmentRepository = apartmentRepository;
}
[HttpPost]
public JsonResult Add(RoomViewModel roomViewModel)
{
try
{
var room = AutoMapper.Mapper.Map<Room>(roomViewModel);
if (_roomRepository.Insert(room))
{
_roomRepository.Save();
var apartRoomViewModel = new ApartmentRoomViewModel
{
ApartmentID = roomViewModel.ApartmentNameID,
RoomID = room.Id
};
var apartRoom = AutoMapper.Mapper.Map<ApartmentRoom>(apartRoomViewModel);
_entities.ApartmentRoom.Add(apartRoom);
_entities.SaveChanges();
}
else
{
return Json(new { status = false, message = "Hata! Ekleme işlemi gerçekleştirilemedi." }, JsonRequestBehavior.AllowGet);
}
return Json(new { status = true, message = "Ekleme işlemi başarılı." }, JsonRequestBehavior.AllowGet);
}
catch
{
return Json(new { status = false, message = "Hata! Ekleme işlemi gerçekleştirilemedi." }, JsonRequestBehavior.AllowGet);
}
}
}
After I added a new room into Room table, I called the last inserted room's Id value to make a new insert to ApartmentRoom table.
Result
ApartmentRoom table
Room table
I want to implement this simple scenario ,which I though EF will support out of the box.
I have a parent record named (Skill) and I am adding child records named (LinktoKB) to it. Now after adding a new LinktoKB, I want to return a view containing the up-to-date list of LinkToKBs (inclusing the newly added one).
Now my Post action method to add new LinktoKB is :-
[HttpPost]
[ValidateAntiForgeryToken]
[CheckUserPermissions(Action = "Edit", Model = "Skill")]
public async Task<ActionResult> AddKBLink(AssignKBLinksToSkill assignkblinkToSkill)
{
try
{
if (assignkblinkToSkill.LinkToKB == null)
{
return HttpNotFound();
}
if (ModelState.IsValid)
{
unitofwork.SkillRepository.AddKBLinkToSkill(assignkblinkToSkill, unitofwork.StaffRepository.GetLoginUserName(User.Identity.Name));
await unitofwork.Save();
//i have removed the values from the model state to prevent showing validation error "that the URL and name is required after succfully adding a new link"
// also to show the modified values and not the binded values
string oldlinkURL = assignkblinkToSkill.LinkToKB.URL;
ModelState.Clear();
var skillAfterAddingKBLink = await unitofwork.SkillRepository.FindSkill(assignkblinkToSkill.Skillid, r => r.LinkToKBs);
assignkblinkToSkill.LinktoKBList = skillAfterAddingKBLink.LinkToKBs.ToList(); //get the new lsit from DB after addign the new link
assignkblinkToSkill.LinkToKB.URL = "http://";//reset the values , so that user will not get old vlues
assignkblinkToSkill.LinkToKB.Name = String.Empty;
if (Request.IsAjaxRequest())
{
TempData["Partialmessage"] = string.Format("{0} URL have been Added", oldlinkURL);
return PartialView("AddKBLink", assignkblinkToSkill);
}
TempData["message"] = string.Format("{0} URL have been Added", oldlinkURL);
return View("AddKBLink", assignkblinkToSkill);
}
}
And my repository methods are:-
public async Task<Skill> FindSkill(int id, params Expression<Func<Skill, object>>[] includeProperties)
{
var query = context.Skills.AsQueryable();
if (includeProperties != null || includeProperties.Count() != 0 || includeProperties[0].Name == "0")
query = includeProperties.Aggregate(query, (current, include) => current.Include(include));
return await query.SingleOrDefaultAsync(a => a.SkillID == id);
}
&
public void AddKBLinkToSkill(AssignKBLinksToSkill assignKBLinkToSkill,string username)
{
var skill = context.Skills.SingleOrDefault(a=>a.SkillID == assignKBLinkToSkill.Skillid);
skill.LinkToKBs.Add(assignKBLinkToSkill.LinkToKB);
skill.Modified = System.DateTime.Now;
skill.ModifiedBy = staffrepo.GetUserIdByUserName(username);
context.Entry(skill).State = EntityState.Modified;
}
Currently I am getting a very strange behavior is that , the list that is returned to the view will not contain the newly added LinkToKB value and it will be replaced by the following value:-
assignkblinkToSkill.LinkToKB.URL = "http://"
so can anyone advice on this please, although I am explicitly retrieving the LinkToKB list from database?
visual studio will how the following at two different stages:-
First this is the newly added LinkToKB:-
Second EF have replace it with the value inside the action method:-
I spend the whole day trying to understand what is going on ... and if i removed these lines:-
assignkblinkToSkill.LinkToKB.URL = "http://";//reset the values , so that user will not get old vlues
assignkblinkToSkill.LinkToKB.Name = String.Empty;
i will get the new up-to-date list correctly (but i need them)..
I have two model classes (Skill & LinktoKB):-
public partial class Skill
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Skill()
{
this.SkillLevels = new HashSet<SkillLevel>();
this.SkillLevelStaffs = new HashSet<SkillLevelStaff>();
this.Customers = new HashSet<Customer>();
this.LinkToKBs = new HashSet<LinkToKB>();
this.SkillVersionHistories = new HashSet<SkillVersionHistory>();
this.Skill1 = new HashSet<Skill>();
this.Skills = new HashSet<Skill>();
}
public int SkillID { get; set; }
public string Name { get; set; }
//code goes here
public virtual SkillStatu SkillStatu { get; set; }
public virtual SkillType SkillType { get; set; }
public virtual ICollection<LinkToKB> LinkToKBs { get; set; }
}
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public LinkToKB()
{
this.Skills = new HashSet<Skill>();
}
public int LinkToKBID { get; set; }
public string URL { get; set; }
public string Name { get; set; }
public virtual ICollection<Skill> Skills { get; set; }
}
and the following viewModel class:-
public class AssignKBLinksToSkill
{
public ICollection<LinkToKB> LinktoKBList { set; get; }
public LinkToKB LinkToKB { set; get; }
public int Skillid { set; get; }
}
In your code there's always one assignkblinkToSkill.LinkToKB instance. When it enters the method it's got some value that you store in the database. Later you re-assign its value to be "http://".
But this is still the instance that you added to the list skillAfterAddingKBLink.LinkToKBs!
You only have to create a new instance in the view model:
assignkblinkToSkill.LinkToKB = new LinkToKB();
assignkblinkToSkill.LinkToKB.URL = "http://";
public int ID { get; set; }
[Required]
public string Surname{get;set;}
[Required (ErrorMessage="FirstName Required")]
public string Firstname{get;set;}
[Required(ErrorMessage="please enter your OtherNames")]
public string Othername{get;set;}
[Required(ErrorMessage="please enter your sex")]
public string Sex{get;set;}
[Required (ErrorMessage="please enter your DateOfBirth")]
public DateTime DateOfBirth{get;set;}
[Required(ErrorMessage="Address is required")]
public string Address{get;set;}
[Required(ErrorMessage="city is required")]
public string City{get;set;}
[Required(ErrorMessage="State is required")]
public string State{get;set;}
public string Country{get;set;}
}
i have created an interface which acts as the middleman between my Domain Layer and my WEBUI
public interface IStudentRepository
{
IQueryable<Student> Student { get; }
//we using a method to save the record into our database
void Save(Student student);
}
the interface is being implented by my repository class which perfoms all the actions of saving the records into the database and retrieving it..
public class EFRepository:IStudentRepository
{
private EFDBContext context = new EFDBContext();
public IQueryable<Student> Student{ get { return context.Students; } }
public void Save(Student student)
{
if (student.ID == 0)
{
context.Students.Add(student);
}
context.SaveChanges();
}
and then i have a view which creates an instance of the student class and uses the interface to store the records in the database, which works perfectly..
[HttpPost]
public ActionResult Registration(Student student)
{
if (ModelState.IsValid)
{
studentrepository.Save(student);
}
return View(student);
}
this works perfectly for me..
But i want to be able to update this same fields incase the student make changes to the fields and it should overwrite the existing record in the database.
i have seen my tutorials where the student id number is passed as an action link before it overwrites the existing record.
however,what i want is the ability for the student to edit the same form using the same button and the same view being display.any help would be appreciated.
You just need to change you repository method to look something like this:
public class EFRepository:IStudentRepository
{
private EFDBContext context = new EFDBContext();
public IQueryable<Student> Student{ get { return context.Students; } }
public void Save(Student student)
{
if (student.ID == 0)
{
context.Students.Add(student);
}
else
{
Student existingStudent = context.Students.FirstOrDefault(x => x.ID == student.ID);
if(existingStudent != null)
{
context.Entry(existingStudent).CurrentValues.SetValues(student);
context.Entry(existingStudent).State = System.Data.Entity.EntityState.Modified;
}
}
context.SaveChanges();
}
or you can use the Entity Framework Attach method as this will automatically track the object state and update the details
I have an entity that I am updating and the method in the controller has these lines in it;
db.Entry(userdetails).State = EntityState.Modified;
try {
db.SaveChanges();
}
I think this is fine, however the entity has a collection in it and these records needs to be created, not updated. I am therefore getting this error;
"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."
I have read that this may be because my AppUserInfo objects have an id of 0 because they need to be added.
The class for the outer entity looks like this;
public class User {
public Guid UserId { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public List<AppUserInfo> InfoList { get; set; }
}
Now in this situation for example, the phone number could have been modified, and the 'InfoList' collection has new items in that need to be created. Some may need to be updated as well. The 'AppUserInfo' class looks like this;
public class AppUserInfo
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int AppUserInfoId { get; set; }
public string info { get; set; }
}
How do I handle this in EF? Am I allowed to save collections in this way? I do not know how to say that there are modifications and additions and possible deletions in the list to EF. Do I simply just remove the line;
db.Entry(userdetails).State = EntityState.Modified;
Any info on the correct way to do this would be very helpful.
Thanks,
db.Entry(userdetails).State = EntityState.Modified;
This line of code is used for editing your objects, if you have no trouble creating your User then all you need is another controller to handle AppUserInfo
Lets imagine that you have a AppUserInfo controller, and you have a AppUserInfo viewModel somewhere. Then you can somthing like the following to accomplish what you want to do.
Your view model like this:
puclic class AppUserInfoCreateViewModels
{
public Guid UserId { get; set; }
public string Info { get; set; }
}
Then your Controller like this:
public class AppUserInfoController : Controller
{
private readonly IYourDataSource _db;
public AppUserInfoController(IYourDataSource db)
{
_db = db;
}
[HttpGet]
public ActionResult Create(int userId)
{
var model = new AppUserInfoCreateViewModels();
model.UserId = userId;
return View(model);
}
[HttpPost]
public ActionResult Create(AppUserInfoCreateViewModels viewModel)
{
if(ModelState.IsValid)
{
var user = _db.Users.Single(d => d.UserId == viewModel.UserId);
var appUserInfo= new AppUserInfo();
appUserInfo.Info= viewModel.Infor;
user.AppUserInfos.Add(appUserInfo);
_db.Save();
return RedirectToAction("detail", "user", new {id = viewModel.UserId});
}
return View(viewModel);
}
}
I hope this helps, ask any questions you may have
I've built my Domain model layer, my repository layer, and now I'm working on my DTO layer to be used by a webApi project. I'm in the middle of implementing an Update service method, and I'm wondering about partial updates. Here's my DTO class:
public class FullPersonDto
{
public FullPersonDto()
{
Friends = new List<Person>();
}
public FullPersonDto(Person person)
{
PersonId = person.PersonId;
DateCreated = person.DateCreated;
Details = person.Details;
Friends = new List<Person>();
foreach (Person friend in person.Friends)
{
Friends.Add(new PersonDto(friend));
}
}
[Key]
public int PersonId { get; set; }
[Required]
public virtual DateTime DateCreated { get; set; }
public virtual string Details { get; set; }
public List<Person> Friends { get; set; }
public Person ToEntity()
{
var person = new Person
{
PersonId = PersonId,
DateCreated = (DateTime) DateCreated,
Details = Details,
Friends = new List<Person>()
};
foreach (PersonDto friend in Friends)
{
person.Friends.Add(friend.ToEntity());
}
return person;
}
}
Here's my Update method in my Repository:
public Person UpdatePerson(Person person)
{
var entry = _db.Entry(person);
if (entry.State == EntityState.Detached)
{
var dbSet = _db.Set<Person>();
Person attachedPerson = dbSet.Find(person.PersonId);
if (attachedPerson != null)
{
var attachedEntry = _db.Entry(attachedPerson);
attachedEntry.CurrentValues.SetValues(person); // what if values are null, like ID, or DateCreated?
}
else
{
entry.State = EntityState.Modified;
}
}
SaveChanges();
return person;
}
My question is: What if I only need to update the Details of a person via my webAPI? Is the convention to construct an entire PersonDto and Update the entire object using SetValues, or is there any way I can specify that I only want a single field updated so that I don't have to send a ton of data over the wire (that I don't really need)?
If it is possible to do partial updates, when is it ever good to update the entire entity? Even if I have to update 5/7 properties, it requires that I send old data for 2/7 to re-write so that SetValues doesn't write nulls into my fields from my DTO.
Any help here would be awesome... totally new to this stuff and trying to learn everything right. Thank you.
I've taken similar approach to do optimization, and I've faced same issues with null values when attaching (not just null, you'll have issue with boolean as well). This is what I've come up with:
public static void Update<T>(this DbContext context, IDTO dto)
where T : class, IEntity
{
T TEntity = context.Set<T>().Local.FirstOrDefault(x => x.Id == dto.Id);
if (TEntity == null)
{
TEntity = context.Set<T>().Create();
TEntity.Id = dto.Id;
context.Set<T>().Attach(TEntity);
}
context.Entry(TEntity).CurrentValues.SetValues(dto);
var attribute = dto.GetAttribute<EnsureUpdatedAttribute>();
if (attribute != null)
{
foreach (var property in attribute.Properties)
context.Entry(TEntity).Property(property).IsModified = true;
}
}
That is extension method for DbContext. Here are the interfaces IDTO and IEntity:
public interface IDTO
{
int Id { get; set; }
}
public interface IEntity
{
int Id { get; set; }
Nullable<DateTime> Modified { get; set; }
Nullable<DateTime> Created { get; set; }
}
I'm using my custom EnsureUpdatedAttribute to annotate what properties should always be updated (to deal with nulls / default values not being tracked):
public class EnsureUpdatedAttribute : Attribute
{
public IEnumerable<string> Properties { get; private set; }
public EnsureUpdatedAttribute(params string[] properties)
{
Properties = properties.AsEnumerable();
}
}
And this is a sample of usage:
public class Sample : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
public Nullable<DateTime> Modified { get; set; }
public Nullable<DateTime> Created { get; set; }
}
[EnsureUpdated("Active")] /// requirement for entity framework change tracking, read about stub entities
public class SampleDTO : IDTO
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[JsonIgnore] /// How to exclude property from going on the wire / ignored for serialization
public bool Active { get; set; }
}
[HttpPost]
public HttpResponseMessage SaveSample(SampleDTO dto)
{
dto.Active = true;
_ctx.AddModel<Sample>(dto);
_ctx.SaveChanges();
return NoContent();
}
return NoContent() is just extension for returning 204 (NoContent).
Hope this helps.
Theres a few options you have, you can create a stored procedure to update the required parts (I wouldnt do this), or you can manually select the fileds to update on the model before saving the context changes with EF.
Heres an example how to update a specific field:
public void UpdatePerson(int personId, string details)
{
var person = new Person() { Id = personId, Details = details };
db.Persons.Attach(personId);
db.Entry(person).Property(x => x.Details).IsModified = true;
db.SaveChanges();
}
It will depend on your scenario what you want to do, but generally speaking its fine to send your whole entity to be updated, and this is how i would approach your situation potentially changing in the future if needed.