我正在尝试在linq to SQL中构建动态查询。简而言之,我想解决的问题如下:
我们有一个现有的SQL Server数据库,其中包含许多我们希望能够一般搜索的表。这是一个遗留数据库,因此我们首先使用实体框架数据(不是代码优先)。 在我们的数据库中,我们还有一个元数据表,其中包含其他表的表名和列名,以及哪些列是可搜索的。
例如,我们可能会有一个名为' Vehicles'使用名为' Vehicle_Id'的PK列,以及名为' Type'的可搜索列。和'颜色'。我们的元数据表将包含列的类型'类型'和'颜色'将它们标记为可搜索。
Vehicle实体的EF模型和映射看起来像这样:
public class Vehicle
{
public int Id { get; set; }
public string Type { get; set; }
public string Colour { get; set; }
}
public class VehicleMap : EntityTypeConfiguration<Vehicle>
{
public VehicleMap()
{
This.ToTable("VEHICLES");
This.HasKey(k => k.Id);
This.Property(p => p.Id).HasColumnName("VEHICLE_ID");
This.Property(p => p.Type).HasColumnName("TYPE");
This.Property(p => p.Colour).HasColumnName("COLOUR");
}
}
用户然后定义搜索要求(例如,&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39;&#39; &#39;蓝色&#39)。这些搜索要求基于列名称。
我希望能够根据元数据表中定义的字段名称动态构建查询,如下所示:
var query = from v in context.Vehicles select v.Id;
foreach (var criterion in criteria)
{
var fieldName = criterion.Field; // Database field name, e.g. "TYPE"
var value = criterion.Value; // Search value, e.g. "CAR"
var filter = [Filter based on field/value]
results = query.Where(filter).ToList();
// do something with results...
}
目前,我认为我在中途使用以下扩展方法,该方法从EF上下文获取给定表的实体映射。我迷失的是然后根据字段名称找到字段(例如&#39; COLOR&#39;)并基于此构建过滤器。
public static EntityType GetTableMapping(this DbContext context, string tableName)
{
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var storageMetadata = ((EntityConnection)objectContext.Connection).GetMetadataWorkspace().GetItems(DataSpace.SSpace);
var entityProps = storageMetadata.Where(s => s.BuiltInTypeKind == BuiltInTypeKind.EntityType).Select(s => s as EntityType);
return (from m in entityProps where string.Compare(m.Name, tableName, StringComparison.OrdinalIgnoreCase) == 0 select m).SingleOrDefault();
}