bfl*_*mi3 12 asp.net-mvc entity-framework circular-reference javascriptserializer
我将我的实体框架实体从我的Web项目和数据访问层拆分为一个单独的类库.在我的控制器中,我调用我的存储库来获取IEnumerable<RobotDog.Entities.Movie>,然后尝试序列化为json使用JavaScriptSerializer但是我得到一个循环引用,即使我正在使用该[ScriptIgnore]属性.
重要提示:最初我在一个项目下拥有我的实体,数据访问和网络,我能够在没有循环引用的情况下成功序列化我的实体.当我创建单独的图层时,我开始遇到问题.我没有改变任何实体.
RobotDog.Entities命名空间中我的一个实体的示例:
namespace RobotDog.Entities {
public class Character {
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[MaxLength(200)]
public string Name { get; set; }
public virtual Person Person { get; set; }
[ScriptIgnore]
public virtual Movie Movie { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
我的控制器:
namespace RobotDog.Web.Controllers {
public class MoviesController : Controller {
private UnitOfWork _unitOfWork = new UnitOfWork();
[HttpGet]
public ActionResult Index() {
var user = Membership.GetUser(User.Identity.Name);
if(user != null) {
var movies = _unitOfWork.UserMovieRepository.Get(u => u.UserId == (Guid) user.ProviderUserKey).Select(m => m.Movie);
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(movies);
return View(json);
}
return View();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的存储库:
namespace RobotDog.DataAccess.Movies {
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class {
internal MovieContext Context;
internal DbSet<TEntity> DbSet;
public Repository(MovieContext context) {
if (context == null)
throw new ArgumentNullException("context");
Context = context;
DbSet = Context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null ) {
IQueryable<TEntity> query = DbSet;
if (predicate != null)
query = query.Where(predicate);
return orderBy != null ? orderBy(query).ToList() : query.ToList();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Đon*_*nny 24
也许有点迟到的反应,但我有POCO类实体框架代码 - Firts的类似问题.问题是可能属性被声明为虚拟.在这种情况下,EF创建代理类来覆盖虚拟属性.似乎默认情况下ScriptIgnore属性不应用于overriden属性,除非你像这样使用它:
[ScriptIgnore(ApplyToOverrides=true)]
Run Code Online (Sandbox Code Playgroud)
圆形对象图不能进行JSON序列化.当你再次考虑它时,它实际上是有意义的.处理此问题的正确方法是使用视图模型.您永远不应将域实体直接传递给您的视图.始终定义仅包含要公开的必要属性的视图模型.
我确信使用此JSON的客户端不关心具有此循环对象图.因此,只需定义一个打破此循环依赖关系的视图模型,并仅包含您需要的属性.
然后,您所要做的就是将您的域模型映射到视图模型,并将此视图模型传递给JsonResult(是的,这是您代码中的另一个问题 - 您手动JSON序列化并在控制器操作中编写管道代码,而不是将其委托给框架).
所以:
[HttpGet]
public ActionResult Index()
{
var user = Membership.GetUser(User.Identity.Name);
if(user != null)
{
IEnumerable<Movie> movies = _unitOfWork
.UserMovieRepository.Get(u => u.UserId == (Guid) user.ProviderUserKey)
.Select(m => m.Movie);
IEnumerable<MovieViewModel> moviesVm = ... map the domain model to your view model
return Json(moviesVm, JsonRequestBehavior.AllowGet);
}
// return an empty movies array
var empty = Enumerable.Empty<MovieViewModel>();
return Json(empty, JsonRequestBehavior.AllowGet);
}
Run Code Online (Sandbox Code Playgroud)
您现在应该关注的重要事情是定义MovieViewModel类,该类将仅包含您希望作为JSON向客户端公开的信息.打破所有循环引用.您可以随意使用此主视图模型引用的其他视图模型,以便映射其他实体.
最重要的是:永远不要将您的域模型传递给视图.始终定义视图模型.这样,您的应用程序完全独立于您正在使用的基础数据访问技术.您可以根据需要随意修改DAL图层,而不会影响UI部件,因为此UI由视图模型表示.
| 归档时间: |
|
| 查看次数: |
7582 次 |
| 最近记录: |