我有一个名为
MSISDN
的复杂类型,如下所示:
public class MSISDN
{
public string NDC { get; set; }
public string CC { get; set; }
public string SN { get; set; }
public string ToString() => $"{NDC}{SN}{CC}";
public string ToLong() => NDC * Math.Power(10, 6) + SN * Math.Power(10,3) + CC;
}
我还为这个复杂类型编写了一个特定的ValueConverter:
public class MsisdnValueConverter : ValueConverter<Msisdn, string>
{
public MsisdnValueConverter() : base(msisdn => msisdn.ToString(), msisdnString => Msisdn.Parse(msisdnString), mappingHints: null) { }
}
哪个序列化/反序列化这个复杂类型。我要写以下查询:
SubscriberCard card = cardDbSet.FirstOrDefault(P => P.Msisdn == msisdn);
此代码引发以下异常:
无法将“System.String”类型的对象转换为“System.Int64”类型。
我尝试使用
ToString()
来避免比较对象,只要它们存储为字符串(或更精确的 NVARCHAR(MAX)
)
因此,在我的下一次尝试中,我使用了以下查询:
SubscriberCard card = cardDbSet.FirstOrDefault(P => P.Msisdn.ToString() == msisdn.ToString());
它还会引发以下异常:
无法翻译。附加信息:方法“object.ToString”的翻译失败。如果此方法可以映射到您的自定义函数,请参阅 https://go.microsoft.com/fwlink/?linkid=2132413 了解更多信息。以可翻译的形式重写查询,或者通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用来显式切换到客户端计算。请参阅 https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息
对我来说唯一可行的方法是通过调用
ToList()
将所有记录检索到内存中。但要花很多钱。
正如最新的例外所说,我将尝试编写 DbFunction,对我来说还有更好的选择吗?
具有转换的属性不能在 LINQ 查询中使用。
在
SubscriberCard
属性中定义,该属性保存真实的数据库字符串并将其映射到表的列。还定义属性Msisdn
,它可以从字符串填充
MSISDN
对象
public class SubscriberCard
{
...
public string MsisdnString {get; set;}
[NotMapped]
public MSISDN Msisdn { get => Msisdn.Parse(MsisdnString); set => MsisdnString = value.ToString(); }
}
并在查询中使用
MsisdnString
属性。
SubscriberCard card = cardDbSet.FirstOrDefault(P => P.MsisdnString == msisdn.ToString());