我有一个自定义类型,例如:
public class Date
{
public int Year {get; }
public int Month {get; }
public int Day {get; }
private Date(int year, int month, int day)
{
// ... Year = year, Month = month, Day = day
}
public static Date Of(string pattern) {
// ... to parse from pattern
// return new Date(year, month, date);
}
public override string ToString(){
// ... string like "2020-02-02"
}
}
}
我想在实体中使用它以字符串形式将其存储在数据库中:
public class Student{
public string Name{get; set; }
public Date CreateDate{get; set; }
public DateTime CreateDate2{get; set; }
}
我有一个DateConverter
可以将Date
对象转换为字符串:
class DateConverter : ValueConverter<Date, string>
{
public DateConvertor(ConverterMappingHints? mappingHints = null) :
base(date => date.ToString(), s => Date.Of(s), mappingHints)
{
}
}
但是我无法应用DateConvertor。
EF核心将日期视为实体类型,而不是实体的属性。
这意味着:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes())
{
// "Date" appears here as an Entity
_logger.Info("Model Entity: {0}", entityType);
foreach (IMutableProperty property in entityType.GetProperties())
{
// I want "Date" appears here as a property.
// Actually "DateTime CreateDate2" appears here.
// I want my "Date" to act like "DateTime"
如何使自定义类型Date
像DateTime
一样充当属性,而不是实体类型?
或
如何将DateConverter
应用于我的Date
?
更新:这是示例之一。
抱歉,我无法共享我的真实代码,因为它们属于我的公司。
但是问题是相同的。
我想知道如何处理所有这类问题。
如果我有一个元数据,将其作为字符串(或数字)存储在数据库中怎么办?
public class Metadata {
public int Field1 {get; }
public string Filed2 {get; }
public double Field3 {get; }
private Metadata(int xxx /* other params */ )
{
// to assign all
}
public static Metadata Parse (string pattern) {
// ... to parse from pattern
// return new Metadata(xxx);
}
public override string ToString(){
// ... string like "abc.id]afe[dfe]fefa"
// using a special encoding
}
}
class MetadataConverter : ValueConverter<Metadata, string>
{
public MetadataConverter(ConverterMappingHints? hints = null) :
base(data => data.ToString(), data => Metadata.Parse(data), mappingHints)
{
}
}
答案 0 :(得分:2)
EF核心将日期视为实体类型,而不是实体的属性。
只有在这种情况下,我才可以使用DateTime代替,没问题。但是我每次都能找到替代解决方案吗?
您可以将值对象注册为complex type
,而不是将其转换为DateTime(在这种情况下但并非在所有情况下都可以使用),这意味着EF将把您的Date
对象解释为拥有它的Student
对象的“属性包”,而不是将其解释为一个单独的实体。简而言之,它将为每个公共财产(天,月,年)创建一个表列(在父实体表,例如[Students]
中)。
但是,这确实需要在属性上使用setter和无参数构造函数,否则EF无法从数据库中呈现您的值对象。
在没有EF可以处理的等效数据类型的情况下(例如DateTime
的{{1}}),这是更好的选择。
答案 1 :(得分:0)
只需在OnModelCreating中配置ValueConverter,如下所示:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var dateConverter = new ValueConverter<Date, string>(
v => v.ToString(),
s => Date.Parse(s)
);
foreach (var et in modelBuilder.Model.GetEntityTypes())
{
foreach (var prop in et.GetProperties().Where(prop => prop.ClrType == typeof(Date)))
{
prop.SetValueConverter(dateConverter);
//modelBuilder.Entity(et.Name).Property(prop.Name).HasConversion(dateConverter);
}
}
}