好的,我正在使用一个旧的 SQL 数据库,它太旧了,以至于最初您无法索引位字段。 所以我有一堆表,其中包含 Y/N 单字符字段。
我终于有机会将东西转移到 C# 和实体框架中。
如果能够在前端将它们“转换”为布尔字段,那将非常方便。 但是当我这样做时,当我查询 Linq to Entities 时,我会破坏它。
例如
db.Carriers.Where(x => x.ActiveBool) 死亡。
db.Carriers.ToList().Where(x => x.ActiveBool) 没有。 但显然,没有查询回 SQL 等
有没有办法实现其中之一(或其他聪明/方便的方法)
您有几个选择。如果可以的话,您可以更新数据库以具有计算字段,然后您可以以这种方式查询它。
您可以为 IsActive 创建一个 [NotMapped] 属性来执行以下操作:
[NotMapped]
public bool IsActive
{
get { return Active == 'Y'; }
set { Active = value ? 'Y' : 'N'; }
}
然后,您可以将“Active”字段设置为Internal,使其指向数据库,但仅适用于模型上的此IsActive列。
但是,为了实际过滤该字段,您必须使用计算列、视图,或者将从上面传入的 IsActive 布尔过滤器转换为“Y”或“N”。否则,您可以在幕后做一些棘手的表达式工作,为您进行此转换,但我认为不值得付出这种努力。一个辅助方法可能就可以了。
char check = Helper.ConvertBoolToChar(entity.IsActive) (returns 'Y' or 'N')
...Where(a => a.Active == check)
好的。我想我至少得到了部分解决方案。
添加到(例如单位类)
public static System.Linq.Expressions.Expression<Func<Units, bool>> IsActive = x => ("Y".Equals(x.Active, StringComparison.OrdinalIgnoreCase)) &&
(x.Carriers == null || "Y".Equals(x.Carriers.Active, StringComparison.OrdinalIgnoreCase));
然后过滤
l = l.Where(Data.Units.IsActive);
我不知道如何在“a”上执行 WHERE 引用导航对象“a.B”作为单独的步骤,但这应该可以满足我的需要。 是时候测试一下了。
是的。这似乎有效。
您可以使用 TypeHandler。我只在读取数据时对此进行了测试,但这对我有用。
public class YnToBoolTypeHandler : SqlMapper.TypeHandler<bool>
{
public override bool Parse(object value) => "Y" == (string?)value;
public override void SetValue(IDbDataParameter parameter, bool value)
{
parameter.DbType = DbType.String;
parameter.Value = value ? "Y" : "N";
}
}
// at program start up
SqlMapper.AddTypeHandler(new YnToBoolTypeHandler());
我正在使用 C# 记录类型(即不可变),因此上面使用 Daniel Lorenz 的第二个属性的解决方案对我不起作用。