我正在使用EF和MVC访问SQL数据库中的数据,并希望控制器使用json进行通信(使用Android中的REST,因此不使用视图)。
我发现有必要更改控制器以通过匿名对象投射数据,以避免主表和引用表之间的循环引用问题,但是现在这在尝试为集合创建json时会导致新问题对象,当基础记录在可选外键字段中包含null时。
表用户(为了示例)有两个外键来代码/描述表语言和国家,语言是强制性的,国家是可选的。
我发现我可以通过测试null id成功地将Country元素替换为null。,json很好......
{
"UserID": 3,
"UpdatedWhen": null,
"Country": null,
"Language": {
"LanguageID": 1,
"LocalName": "English"
}
}
...但现在发现当我有多个User对象需要处理时,这不起作用。
public JsonResult Index()
{
var users = from user in db.Users
select new
{ user.UserID,
< snip >
user.CreatedWhen,
user.UpdatedBy,
user.UpdatedWhen,
Country = (user.Country == null ? null : new { user.Country.CountryID, user.Country.LocalName }),
Language = new { user.Language.LanguageID, user.Language.LocalName } };
return Json(users.ToList(), JsonRequestBehavior.AllowGet);
}
从我读过的问题是我的.ToList(),它不喜欢null的Country对象,因为如果我只处理一个用户,例如。
private object projectUser(User user)
{
return new
{
user.UserID,
< snip >
user.UpdatedWhen,
Country = (user.Country == null ? null : new { user.Country.CountryID, user.Country.LocalName }),
Language = new { user.Language.LanguageID, user.Language.LocalName } };
......它运作得很好。
我一直在寻找,但根本找不到一个类似的如何更好地做到这一点的例子,任何人都可以建议一种方式。
提前致谢。
答案 0 :(得分:1)
您无法在null
个查询中创建linq to entity
常量值,这就是此行users.ToList()
告诉您何时执行该行....
并且此方法private object projectUser(User user)
正常工作,因为user
已经在内存中获取....
要解决您的问题,您可以获取数据,然后在内存中选择您的数据,如下所示:
var users = (from user in db.Users
join country in db.Countries on user.CountryID equals country.ID into joinedList
from country in joinedList.DefaultIfEmpty()
select new {user, country})
.ToList() // your data fetched to memory by this line
.Select(u => new
{
u.user.UserID,
u.user.CreatedWhen,
u.user.UpdatedBy,
u.user.UpdatedWhen,
Country = (u.country == null ? null : new { u.country.CountryID, u.country.LocalName }),
Language = new { u.user.Language.LanguageID, u.user.Language.LocalName } }
})
.ToList();
作为替代方案,您可以将国家/地区(anonymouse type)
的属性设置为默认值,而不是null
,如下所示:
var users = (from user in db.Users
join country in db.Countries on user.CountryID equals country.ID into joinedList
from country in joinedList.DefaultIfEmpty()
select new {
user.UserID,
user.CreatedWhen,
user.UpdatedBy,
user.UpdatedWhen,
Language = new { user.Language.LanguageID, user.Language.LocalName },
Country = new {
CountryID = country == null ? default(Guid) : country.CountryID, // i assume type of CountryID is Guid
LocalName = country == null ? "" : country.LocalName
}
})
.ToList();
答案 1 :(得分:0)
打破查询,看看每一步的结果是什么,找出问题来自你的数据:
var UsersQuery = (from user in db.Users
join country in db.Countries on user.CountryID equals country.ID into joinedList
from country in joinedList.DefaultIfEmpty()
select new {user, country})
.ToList(); // your data fetched to memory by this line
var Users = UsersQuery.Select(u => new
{
u.user.UserID,
u.user.CreatedWhen,
u.user.UpdatedBy,
u.user.UpdatedWhen,
Country = (u.country == null ? null : new { u.country.CountryID, u.country.LocalName }),
Language = new { u.user.Language.LanguageID, u.user.Language.LocalName } }
})
.ToList();