我正在开发Asp.net Core 2 MVC项目,如下所示。通过删除我们应该熟悉的部分,我将尽可能简化代码片段。
实体模型
public class Customer
{
public string Id { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string Country { get; set; }
}
数据库上下文
public class AppDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
}
按国家,公司名称和其他人搜索的辅助类
public class Search
{
public enum Options
{
[Display(Name="By Country")]
ByCountry = 1,
[Display(Name = "By Company Name")]
ByCompanyName = 2,
// in the future there will be other items appended
}
public AppDbContext Context { get; }
public IDictionary<Options, Func<string, IEnumerable<Customer>>> SearchMethods { get; }
public Search(AppDbContext context)
{
Context = context;
SearchMethods =
new Dictionary<Options, Func<string, IEnumerable<Customer>>>()
{
[Options.ByCountry] = x => Context.Customers
.Where(c => c.Country.ToLower().Contains(x.ToLower()))
.ToList(),
[Options.ByCompanyName] = x => Context.Customers
.Where(c => c.CompanyName.ToLower().Contains(x.ToLower()))
.ToList()
// in the future there will be other items appended
};
}
}
Search
允许我在控制器和视图中避免使用硬编码的文字字符串。以下是示例:
控制器
public class HomeController : Controller
{
public Search S { get; }
public HomeController(Search s) => S = s;
[HttpPost]
public IActionResult Search(string criteria, Search.Options searchBy)
=> View(S.SearchMethods[searchBy](criteria));
}
查看
<input name="criteria" />
<select name="searchBy" asp-items="Html.GetEnumSelectList<Search.Options>()"></select>
我意识到逐渐向Options
枚举添加新元素并向SearchMethods
字典属性添加新项目不会产生版本问题,只要我能确保Options
的元素是在数字上保持相同的顺序。
现在我关心的是这种方法是否有任何缺点?例如,关于性能问题,可伸缩性问题,因为每个SearchMethods
实例都有一个字典Search
的实例。
欢迎任何意见和建议。
这是我迄今为止做出的最后决定。我使用字典将注册转换为使用switch
进行查找,如下所示。
public class Search
{
public enum Options
{
[Display(Name = "By Country")]
ByCountry = 1,
[Display(Name = "By Company Name")]
ByCompanyName = 2,
[Display(Name = "By Contact Name")]
ByContactName = 3
}
public AppDbContext Context { get; }
public Search(AppDbContext context) => Context = context;
public IEnumerable<Customer> Filter(string criteria, Options options)
{
IEnumerable<Customer> customers = Context.Customers;
string lowCriteria = criteria.ToLower();
switch (options)
{
case Options.ByCountry:
customers = customers.Where(c => c.Country.ToLower().Contains(lowCriteria));
break;
case Options.ByCompanyName:
customers = customers.Where(c => c.CompanyName.ToLower().Contains(lowCriteria));
break;
case Options.ByContactName:
customers = customers.Where(c => c.ContactName.ToLower().Contains(lowCriteria));
break;
}
return customers.ToList();
}
}
答案 0 :(得分:1)
您可以使用实际方法使整个课程更容易阅读,并允许您直接使用这些查询,例如用于测试:
public class Search
{
public AppDbContext Context { get; }
public IDictionary<Options, Func<string, IEnumerable<Customer>>> SearchMethods { get; }
public Search(AppDbContext context)
{
Context = context;
SearchMethods = new Dictionary<Options, Func<string, IEnumerable<Customer>>>()
{
[Options.ByCountry] = GetByCountry,
[Options.ByCompanyName] = GetByCompanyName,
};
}
public IEnumerable<Customer> GetByCountry (string countryName)
{
return Context.Customers
.Where(c => c.Country.ToLower().Contains(countryName.ToLower()))
.ToList();
}
public IEnumerable<Customer> GetByCompanyName (string companyName)
{
return Context.Customers
.Where(c => c.CompanyName.ToLower().Contains(companyName.ToLower()))
.ToList()
}
}
这仍然存在为每个Search
实例创建(基本上是常量的)字典的开销,这意味着每个对范围服务的请求。
我们可以通过静态查找来避免这种情况。不幸的是,我们只能对静态方法执行此操作,因此我们必须稍微更改它们以获取数据库上下文。我们在Search
实例中添加了一个实用工具方法:
public class Search
{
private static IDictionary<Options, Func<AppDbContext, string, IEnumerable<Customer>>> _searchMethods { get; }
public AppDbContext Context { get; }
static Search()
{
_searchMethods = new Dictionary<Options, Func<AppDbContext, string, IEnumerable<Customer>>>()
{
[Options.ByCountry] = GetByCountry,
[Options.ByCompanyName] = GetByCompanyName,
};
}
public Search(AppDbContext context)
{
Context = context;
}
public IEnumerable<Customer> Get(Options query, string argument)
=> _searchMethods[query](Context, argument);
public static IEnumerable<Customer> GetByCountry (AppDbContext context, string countryName)
{
return context.Customers
.Where(c => c.Country.ToLower().Contains(countryName.ToLower()))
.ToList();
}
public static IEnumerable<Customer> GetByCompanyName (AppDbContext context, string companyName)
{
return context.Customers
.Where(c => c.CompanyName.ToLower().Contains(companyName.ToLower()))
.ToList()
}
}