繁体   English   中英

如何使用实体框架管理的类的属性创建动态过滤器?

[英]How to create a dynamic filter using the attributes of a class managed by the Entity Framework?

我正在使用 Entity Framework 6 开发应用程序,但我无法使用 Entity Framework 管理的实体类的属性来解决动态过滤器的问题。

问题实际上是类的不可为空的属性(可以与空值进行比较)。

背景

我正在使用传统框架将应用程序分成 3 个项目(模型、视图、控制器)和 C#。

使用 SQL Server 2017 作为数据库和实体框架(不是核心)。

我试过的

我做了几次谷歌查询,但没有一个解决我的问题。

最接近解决方案的答案是这里的Entity Framework Core - 动态过滤用户 Marcio Martins,但我没有看到有关如何处理不可为空属性的任何信息。

有谁知道如何解决这个问题?

代码

我需要找到一种方法将下面的查询转换为 lambda 或 linq 表达式:

-- Sql Server query
declare @ProductID int
declare @Name nvarchar(600)
declare @BarCode nvarchar(26)
declare @Active bit
declare @Price decimal

select
    p.ProductID
    , p.Name
    , p.BarCode
    , p.Active
    , p.Price
from
    Product p
where
    (@ProductID is null or p.ProductID = @ProductID)
    and (@Name is null or p.Name = @Name)
    and (@BarCode is null or p.BarCode = @BarCode)
    and (@Active is null or p.Active = @Active)
    and (@Price is null or p.Price = @Price)

实体类

public class Package
{
    [Key]
    public Int32 PackageID { get; set; }
    [Required]
    [MaxLength(20)]
    public String Name { get; set; }
    public Boolean Active { get; set; }
}

View 中的片段代码。

List<Package> packages = new PackageController().Retrieve();
// Dynamic query here!

编辑

我试过这个,但它不起作用:

List<Package> packages = new PackageController().Retrieve()
                                                .Where(p =>  String.IsNullOrEmpty(p.Name) || p.Name.Contains(package.Name))
                                                .ToList();

预期的:

主要思想是使查询灵活,以便最终用户可以通过实体类的任何属性过滤数据。

例如:用户选择名称或包名称的一部分并且不指示记录是否处于活动状态,考虑到上述查询,只会通知 Name 属性,Active 属性将接收空值,查询将返回所有值,其中包名称是用户选择的值,无论它是活动的还是停用的。

实际结果

由于我不能调整动态过滤器,那么如果用户通知包的“名称”属性或“名称”的一部分,并且没有说明它是否处于活动状态,.NET会自动初始化“活动”的值" 包的属性为 false,这最终会返回所有禁用的包,其名称或名称的一部分由用户选择。

使属性Active 可以为空(因此它匹配数据库中的字段类型),它将解决您的问题。

实体类:

public class Package
{
    ...
    public Boolean? Active { get; set; }
}

非常感谢您的观看和回复。

经过一些测试和 Przemek Marcinkiewicz 在他的回答中给我的想法,我能够解决问题

来吧,这个答案可以在未来帮助很多人。

我需要使 Package 类的属性可以为空,但在不更改银行模型的情况下,我通过像这样配置类来做到这一点:

public class Package
{
    [Key]
    [Required]
    public Int32? PackageID { get; set; }
    [Required]
    [MaxLength(20)]
    public String Name { get; set; }
    [Required]
    public Boolean Active? { get; set; }
}

到目前为止,好吧,我需要以某种方式使用我的查询机制,并且我能够通过调用称为过程的实体框架并使用可为空参数来做到这一点,最终结果是这样的:

public List<Package> Retrieve(Package entity)
{
    using (MyDatabaseContext db = new MyDatabaseContext())
    {
        return db.Database
            .SqlQuery<Package>
            (
                "PROC_PACKAGE_SELECT @PackageID, @Name, @Active"
                , new SqlParameter("@PackageID", (object)entity.PackageID ?? DBNull.Value)
                , new SqlParameter("@Name", (object)entity.Name ?? DBNull.Value)
                , new SqlParameter("@Active", (object)entity.Active ?? DBNull.Value)
            )
                .ToList<Package>();
    }
}

我运行了几次测试,在那种情况下,查询 100% 灵活满足我的需求。

我真的希望这项努力可以帮助社区中的某个人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM