У меня есть некоторый код MVC, который сериализирует объект EF 3.5 в анонимный тип для возврата, поскольку результат JSON к Ajax обращается к моей странице. Препятствие, которое я имею, - то, что, когда я передаю объект обратно серверу через JSON, (и позволяют ModelBinder десериализовать его для меня в мой тип EF), я должен обновить его в своем контексте Платформы Объекта вручную. Или по крайней мере это - то, что я делаю теперь. Это не имеет никакого EntityKey, таким образом присоединение его перестало работать. Я заканчиваю тем, что имел необходимость искать старый объект и обновить его свойство свойством. Какие-либо идеи вокруг этого? Решение состоит в том, чтобы раздать EntityKey с моим объектом?
Вот то, что я имею:
public void Update(Album album)
{
using (var db = new BandSitesMasterEntities())
{
var albumToUpdate = db.Album.First(x => x.ID == album.ID);
albumToUpdate.AlbumTitle = album.AlbumTitle;
albumToUpdate.Description = album.Description;
albumToUpdate.ReleaseYear = album.ReleaseYear;
albumToUpdate.ImageURL = album.ImageURL;
albumToUpdate.OtherURL = album.OtherURL;
db.SaveChanges();
}
}
И вот то, что я хотел бы сделать, или что-то подобное:
public void Update(Album album)
{
using (var db = new BandSitesMasterEntities())
{
db.Attach(album)
db.SaveChanges();
}
}
Невозможно обойти проблему с ключом сущности. Вы должны либо добавить его к своему анонимному типу, либо я бы рекомендовал вам перенести свой код на использование служб данных.
http://www.hanselman.com/blog/jQueryToShipWithASPNETMVCAndVisualStudio.aspx
, что позволит вам выполнять все манипуляции с БД на стороне клиента.
Вы пробовали что-то вроде:
object original;
var key = contexte..CreateEntityKey("EntitySet", modified);
if(contexte.TryGetObjectByKey(key, out original))
{
var originalEntity = (YourEntityType)original;
// You have to mannualy set your entityKey
originalEntity.YourEntityReference.EntityKey = new EntityKey("Entities.EntitySet", "Id", modified.YourEntity.Id);
contexte.ApplyPropertyChanges("EntitySet", modified);
}
contexte.SaveChanges();
Предполагая, что ваша EntityReference установлена с помощью dropDown, вы все равно будете иметь идентификатор
{{1} }или вы можете использовать AutoMapper для отображения этих полей за вас, так что вы просто добавите одну дополнительную строку в ваш пример.
В EF 4.0 это стало для нас намного проще. Это то, что мы сделали в EF 3.5:
public static void AttachAsModified(this ObjectContext objectContext, string setName, object entity,
IEnumerable<String> modifiedFields)
{
objectContext.AttachTo(setName, entity);
ObjectStateEntry stateEntry = objectContext.ObjectStateManager.GetObjectStateEntry(entity);
foreach (String field in modifiedFields)
{
stateEntry.SetModifiedProperty(field);
}
}
А затем:
using (var db = new BandSitesMasterEntities())
{
db.AttachAsModified("Album", album, new string[] { "AlbumTitle", "Description", "ReleaseYear", "ImageURL", "OtherURL" })
db.SaveChanges();
}
Это становится более сложным, если у вас есть ограничения внешнего ключа, но похоже, что у вас их нет.
Почему бы вместо этого просто не использовать методы контроллера UpdateModel или TryUpdateModel? Это очень хорошо работает с EF, и вы даже можете явно установить список включенных свойств.
Параметр id будет автоматически отображаться через фреймворк MVC на скрытое поле вашей формы, указывающее на id.
public void Update(int id, FormCollection collection)
{
using (var db = new BandSitesMasterEntities())
{
var albumToUpdate = db.Album.First(x => x.ID == id);
//use UpdateModel to update object, or even TryUpdateModel
UpdateModel(albumToUpdate, new string[] { "AlbumTitle", "Description", "ReleaseYear", "ImageURL", "OtherURL" });
db.SaveChanges();
}
}
В частичном классе сущности Album вы можете определить функцию CopyFrom и вызвать ее из функции Update
partial class Album
{
public void CopyFrom(Album album)
{
//individual field copying here
}
}
public void Update(Album album)
{
...
albumToUpdate.CopyFrom(album);
...
}