通过 Web 传输实体框架对象并通过 JSON 返回的最佳方式
Posted
技术标签:
【中文标题】通过 Web 传输实体框架对象并通过 JSON 返回的最佳方式【英文标题】:Best way to transfer an Entity Framework object over the web and back via JSON 【发布时间】:2011-01-11 00:50:30 【问题描述】:我有一些 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();
【问题讨论】:
为什么不使用数据服务? @ashraf,他说他正在使用 EF 3.5 【参考方案1】:或者您可以使用 AutoMapper 为您映射这些字段,因此您只需在示例中添加一行。
【讨论】:
实际上是 2 行 - 检索密钥然后映射。【参考方案2】:为什么不直接使用 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();
【讨论】:
【参考方案3】:在 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();
如果你有外键约束会变得更复杂,但看起来你没有。
【讨论】:
【参考方案4】:没有办法解决实体密钥问题。您要么必须将其添加到您的匿名类型,要么我建议您将代码移植到使用数据服务。
http://www.hanselman.com/blog/jQueryToShipWithASPNETMVCAndVisualStudio.aspx
这将允许您在客户端执行所有数据库操作。
http://msdn.microsoft.com/en-us/data/bb931106.aspx
【讨论】:
【参考方案5】:您是否尝试过类似的方法:
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 设置的,你仍然有 Id
【讨论】:
【参考方案6】:在您的 Album 实体的分部类中,您可以定义一个 CopyFrom 函数并从您的 Update 函数中调用它
partial class Album
public void CopyFrom(Album album)
//individual field copying here
public void Update(Album album)
...
albumToUpdate.CopyFrom(album);
...
【讨论】:
以上是关于通过 Web 传输实体框架对象并通过 JSON 返回的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章