我正在使用带有Database First的EF6开发ASP.NET MVC项目。我正在尝试使用Redis server
来缓存经常使用的对象。
但是我在保存相关实体(父子)方面遇到了问题。例如,Author
和Author_Book
类之后是父子并且相互引用(RDBMS中的外键约束)
public partial class Author
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Author_Book> Author_Book { get; set; }
}
public partial class Author_Book
{
public int Id { get; set; }
public int AuthorId { get; set; }
public string Title { get; set; }
public virtual Author Author { get; set; }
}
public partial class Customer
{
public int ID { get; set; }
public string CustomerName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
查询并尝试将查询结果存储到Redis server
,如下所示
using (EFTestContext db = new EFTestContext())
{
var data = db.Authors.ToList();
redisClient.Set<List<Author>>("author", data);
}
redisClient.Set..
Exception
行以上
An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll
但是,如果我将Customer实体(没有子实体)存储到Redis server
中,它可以正常工作
using (EFTestContext db = new EFTestContext())
{
var customers = db.Customers.ToList();
redisClient.Set<List<Customer>>("customers", customers);
}
所以我的问题是如何将完整的实体(带有孩子)存储到redis服务器中?
答案 0 :(得分:1)
我遵循[DataContract] / [DataMember]
方法(正如评论中提到的@oferzelig)。它工作正常,不再提出异常。我在这里描述它可以帮助其他人。
EF数据库 - 默认情况下不添加[DataContract] / [DataMember]
属性,我们需要修改它的T4模板。我在模型模板Model1.tt
中进行了以下修改。
在行
之前添加了[DataContract]
属性
<#=codeStringGenerator.EntityClassOpening(entity)#>
现在看起来像
[DataContract]
<#=codeStringGenerator.EntityClassOpening(entity)#>
在行
之前添加了[DataMember]
属性
<#=codeStringGenerator.Property(edmProperty)#>
看起来像
[DataMember]
<#=codeStringGenerator.Property(edmProperty)#>
我们还需要为一对多关系生成[DataMember]
属性(例如,问题为public virtual ICollection<Author_Book> Author_Book { get; set; }
),但 NOT 为一对一生成(例如{{ 1}}问题)。为了实现它,我在public virtual Author Author { get; set; }
类
CodeStringGenerator
并在行
之前调用它public string NavigationProperty_NeedDataMember(NavigationProperty navProp)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0}",
navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("[DataMember]") : ""
);
}
如下
<#=codeStringGenerator.NavigationProperty(navigationProperty)#>
最后修改了<#=codeStringGenerator.NavigationProperty_NeedDataMember(navigationProperty)#>
<#=codeStringGenerator.NavigationProperty(navigationProperty)#>
程序以添加UsingDirectives
,如下所示
System.Runtime.Serialization
那一切。
现在它正在生成以下类,我不需要在每次更新后手动编辑类。
public string UsingDirectives(bool inHeader, bool includeCollections = true)
{
return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
? string.Format(
CultureInfo.InvariantCulture,
"{0}using System;{1}" +
"{2}" +
"{3}",
inHeader ? Environment.NewLine : "",
includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
includeCollections ? (Environment.NewLine + "using System.Runtime.Serialization;") : "",
inHeader ? "" : Environment.NewLine)
: "";
}
希望它会帮助别人。