假设我有一个简单的模型:
public class Movie
{
public int ID { get; set; }
public string Name { get; set; }
}
和DbContext:
public class MoviesContext : DbContext
{
...
public DbSet<Movie> Movies { get; set; }
}
另外,我在MoviesContext类中有一个方法可以通过子字符串过滤电影,如下所示:
return Movies.Where(m => m.Name.Contains(filterString)).Select(m => m);
现在假设我想添加一个新模型,比如说:
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string FullName { get { return FirstName + (MiddleName?.Length > 0 ? $" {MiddleName}" : "") + $" {LastName}"; } }
}
我还想按名称(即FullName)过滤人(DbSet人).我想要DRY,所以最好概括一下MoviesContext的过滤方法.而且,重要的是,我想在数据库级别进行过滤.所以我必须处理LINQ for Entities.
如果不是这样,任务很简单.我可以使用抽象类并添加一个执行“包含子串”逻辑的虚方法.或者,我可以使用界面.不幸的是,由于LINQ for Entities,我不能使用FullName属性(这不方便但可以忍受),我不能写这样的东西:
return dbset.Where(ent => ent.NameContains(filterString)).Select(ent => ent);
那么,如何解决这个问题呢?我找到了一些解决方案(几乎让我的头坏了),但我对此并不满意.我将单独发布我的解决方案,但我希望有一个更优雅的解决方案.
最佳答案 仔细阅读你的代码,而不是你的NameFilterable抽象类,你不能做这样的事情:
public interface IHasPredicateGetter<T> {
[NotNull] Expression<Func<T, bool>> GetPredicateFromString([NotNull] string pValue);
}
public class Movie : IHasPredicateGetter<Movie> {
public int ID { get; set; }
public string Name { get; set; }
public Expression<Func<Movie, bool>> GetPredicateFromString(string pValue) {
return m => m.Name.Contains(pValue);
}
}
例如,这可以防止您需要演员表.你很难理解你在这里想做什么,所以我不确定这是不是完整的事情.您仍然坚持使用可能是静态方法的实例方法,但是否则无法实现接口.