背景
我有一个API,它使用两个表(标记和区域)从数据库中检索数据。每个令牌都有一个与Area对象相关的AreaID。我首先使用Entity Framework数据库。
问题:
当我尝试查询数据库以获取令牌(应包含对区域的引用)时。我收到一个错误:
Error getting value from 'Area' on 'System.Data.Entity.DynamicProxies.Token_51B85DEDCE118919D07024535C24194E890BF0A8499689750190733A8008D739'."
代码:
以下是由EF创建的模型:
public partial class Token
{
public System.Guid ID { get; set; }
public System.DateTime Expiry { get; set; }
public System.Guid Reference { get; set; }
public string IPAddress { get; set; }
public string TokenValue { get; set; }
public Nullable<System.Guid> Area_ID { get; set; }
public virtual Area Area { get; set; }
}
public partial class Area
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Area()
{
this.Tokens = new HashSet<Token>();
}
public System.Guid ID { get; set; }
public string Name { get; set; }
public string UriPrefix { get; set; }
public string Description { get; set; }
public System.DateTime Created { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Token> Tokens { get; set; }
}
这是我查询数据库(修剪)的地方:
using (var dbContext = new APIEntities())
{
try
{
tokenObject = dbContext.Tokens.Where(t => t.TokenValue == decryptedToken).FirstOrDefault();
// the tokenObject is created but the Area property is null.
} catch (Exception ex) {
string message = ex.Message.ToString();
}
}
以下是序列化JSON的方法:
public HttpResponseMessage LogIntoAppWithToken()
{
string result = "";
string jsonString = "failed to get JSON";
string message = "";
try
{
var re = Request;
var headers = re.Headers;
EncryptedToken encToken = new EncryptedToken();
TokenChecker tokenChecker = new TokenChecker();
encToken.tokenValue = "";
if (headers.Contains("X-TOKEN"))
{
encToken.tokenValue = headers.GetValues("X-TOKEN").First();
}
result = tokenChecker.IsTokenValid(encToken).ToString();
Token retrievedToken = tokenChecker.GetTokenByTokenValue(encToken.tokenValue);
jsonString = JsonConvert.SerializeObject(retrievedToken);
// ERROR Here ^^
} catch (Exception ex) {
message = ex.Message.ToString();
}
return Request.CreateResponse(HttpStatusCode.OK, "Token is valid: " + result + ". " + " " + jsonString + " " + " Any error messages: " + message);
}
我尝试了什么:
创建dbContext时,我使用了:
dbContext.Configuration.ProxyCreationEnabled = false;
dbContext.Configuration.LazyLoadingEnabled = false;
在WebApiConfig中:
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
在Global.asax的Application_start中:
config.Formatters.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
我甚至尝试从tokenObject获取AreaID并查询数据库以手动获取区域&#39;然后将此检索到的Area对象添加到tokenObject(覆盖null版本):
Area areaObject = dbContext.Areas.Where(a => a.ID == tokenObject.Area_ID).FirstOrDefault();
tokenObject.Area = areaObject;
但这会导致自引用循环错误。 (这个想法更多的是用于测试而不是用作解决方案)。
我需要做些什么才能检索包含Area作为其属性之一的Token,然后序列化为JSON字符串?
修改1
我注意到Token对象现在包含Area对象,但Area对象包含一个包含Area的Token?这一直在继续...
根据我的设置,令牌肯定包含区域但区域不应包含令牌?
答案 0 :(得分:1)
经过大量的搜索后,我找到了另一个适合我的answer。
只需将[JsonIgnore]属性添加到受影响的属性即可。对于我的区域模型:
[JsonIgnore]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Token> Tokens { get; set; }
答案 1 :(得分:0)
使用包含:
tokenObject = dbContext.Tokens
.Where(t => t.TokenValue == decryptedToken)
.Include(t => t.Area)
.FirstOrDefault();
答案 2 :(得分:0)
如果您不想序列化引用的实体,请使用以下选项之一。
为避免延迟加载所有实体,请将LazyLoadingEnabled设置为false 在您的bdContext类中。
public SchoolDBEntities(): base("name=SchoolDBEntities")
{
this.Configuration.LazyLoadingEnabled = false;
}
不用担心,您仍然可以通过调用Include方法来访问引用的实体。 示例:-
var list = context.Customers
.Include(c => c.Invoices)
.ToList();