存储库模式仅检索所需的列 [英] Repository Pattern Retrieve Desired Columns Only
问题描述
我正在使用示例 here 创建一个具有工作单位的存储库模式。
I am using the example here to create a repository pattern with Unit of Work.
在代码中有一个通用的Get方法:
Within the code, there is a generic Get method:
public class GenericRepository<TEntity> where TEntity : class
{
internal AdminDbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(AdminDbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<TEntity, TEntity> selector = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ','}, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
此时调用此方法时,从数据库中获取记录,并在内存中进行列选择。
At this moment when this method is called, all the records from the database are fetched and column selection is done in memory.
我的问题是我如何在这里扩展Get方法,让我动态地将列名称传递给这个方法只能在数据库级别选择所需的列?
My question is how can I extend the Get method here that would allow me to dynamically pass column names to this method so that only the desired columns are selected at database level?
我试过:
- 使用所需列的逗号分隔值接受一个字符串参数,但是我无法将其映射到实体。
- 创建一个具有相同类型的过滤器的参数给出错误。
推荐答案
这是一个很长的答案,但这里是一个扩展方法我创造了这样做。在这种情况下,我返回一个对象,因为这在webAPI中用于返回json,我不需要一个特定的类型,但是这可以很容易地适应于返回一个通用实体类型。
This is kind of a long answer but here is an extension method I created for doing this. I am returning an object in this case because this is used in webAPI to just return json and I do not need a particular type but this can easily be adapted to return a generic entity type.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json.Linq;
namespace Your.Extensions
{
public enum PropertyFormat
{
AsIs,
PascalCase,
CamelCase
}
public static class DataShapingExtensions
{
public static object ToDataShape<ObjectIn>(this ObjectIn objectToShape, string fields, PropertyFormat propertyFormat = PropertyFormat.AsIs) where ObjectIn : class
{
var listOfFields = new List<string>();
if (!string.IsNullOrWhiteSpace(fields))
{
listOfFields = fields.ToLower().Split(',').ToList();
}
if (listOfFields.Any())
{
var objectToReturn = new JObject();
//====
var enumerable = objectToShape as IEnumerable;
if (enumerable != null)
{
var listOfObjects = new List<JObject>();
foreach (var item in enumerable)
{
var objectToReturn2 = new JObject();
listOfFields.ForEach(field =>
{
try
{
var prop = item.GetType()
.GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var fieldName = prop.Name;
var fieldValue = prop.GetValue(item, null);
fieldName = GetName(fieldName, propertyFormat);
objectToReturn2.Add(new JProperty(fieldName, fieldValue));
}
catch (Exception ex) { }
});
listOfObjects.Add(objectToReturn2);
}
return listOfObjects.ConvertAll(o => o);
}
//====
listOfFields.ForEach(field =>
{
try
{
var prop = objectToShape.GetType()
.GetProperty(field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var fieldName = prop.Name;
var fieldValue = prop.GetValue(objectToShape, null);
fieldName = GetName(fieldName, propertyFormat);
objectToReturn.Add(new JProperty(fieldName, fieldValue));
}
catch (Exception ex) { }
});
return objectToReturn;
}
return objectToShape;
}
private static string GetName(string field, PropertyFormat propertyFormat)
{
switch (propertyFormat)
{
case PropertyFormat.AsIs: return field;
case PropertyFormat.PascalCase: return field.ToPascalCase();
case PropertyFormat.CamelCase: return field.ToCamelCase();
default: return field;
}
}
}
}
/用法
[HttpGet, Route("api/someroute")]
public async Task<IHttpActionResult> YourMethod(string fields = null)
{
try
{
var products = await yourRepo.GetProductsList();
if (fields.HasValue())
{
return Ok(products.ToDataShape(fields, PropertyFormat.CamelCase));
}
return Ok(products);
}
catch (Exception)
{
return InternalServerError();
}
}
//呼叫路由
/api/someroute?fields=productID,productName
//输出(json)
//output (json)
{
productID: 1,
productName: "Some Name"
}
这篇关于存储库模式仅检索所需的列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!