C# 获取类所需的属性
我有大约15个实体,我必须为它们获取id和name属性。首先,我检查是否可以从本地缓存中提取属性。若并没有,那个么我通过代码从数据库中获取它们并保存在缓存中 以下是我针对两个实体的代码:C# 获取类所需的属性,c#,.net-core,entity-framework-core,C#,.net Core,Entity Framework Core,我有大约15个实体,我必须为它们获取id和name属性。首先,我检查是否可以从本地缓存中提取属性。若并没有,那个么我通过代码从数据库中获取它们并保存在缓存中 以下是我针对两个实体的代码: public class GetParamsService : IGetParamsService { private readonly IMemoryCache _cache; private readonly MemoryCacheEntryOptions _cacheOptions;
public class GetParamsService : IGetParamsService
{
private readonly IMemoryCache _cache;
private readonly MemoryCacheEntryOptions _cacheOptions;
private readonly IDealTypeRepository _dealTypeRepository;
private readonly ICurrencyRepository _currencyRepository;
public GetParamsService(IMemoryCache memoryCache,
IDealTypeRepository dealTypeRepository,
ICurrencyRepository currencyRepository)
{
_cache = memoryCache;
_cacheOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromHours(2));
_dealTypeRepository = dealTypeRepository;
_currencyRepository = currencyRepository;
}
public async Task<(int idDealType, string dealTypeName)> GetDealTypeParams(
string dealTypeCode)
{
if (!_cache.TryGetValue(CacheKeys.IdDealType, out int idDealType)
| !_cache.TryGetValue(CacheKeys.DealTypeName, out string dealTypeName))
{
var dealType = await _dealTypeRepository
.Get(x => x.Code == dealTypeCode, dealTypeCode);
idDealType = dealType.IdDealType;
dealTypeName = dealType.Name;
_cache.Set(CacheKeys.IdDealType, idDealType, _cacheOptions);
_cache.Set(CacheKeys.DealTypeName, dealTypeName, _cacheOptions);
}
return (idDealType, dealTypeName);
}
public async Task<(int idCurrency, string currencyName)> GetCurrencyParams(
string currencyCode)
{
if (!_cache.TryGetValue(CacheKeys.IdCurrency, out int idCurrency)
| !_cache.TryGetValue(CacheKeys.CurrencyName, out string currencyName))
{
var currency = await _currencyRepository
.Get(x => x.Code == currencyCode, currencyCode);
idCurrency = currency.IdCurrency;
currencyName = currency.Name;
_cache.Set(CacheKeys.IdCurrency, idCurrency, _cacheOptions);
_cache.Set(CacheKeys.CurrencyName, currencyName, _cacheOptions);
}
return (idCurrency, currencyName);
}
}
每个存储库都是通过Get方法从GenericRepository继承的:
public class DealTypeRepository : GenericRepository<DealTypeEntity>, IDealTypeRepository
{
public DealTypeRepository(DbContextOptions<MyContext> dbContextOptions)
: base(dbContextOptions)
{
}
}
public class GenericRepository<TEntity> where TEntity : class
{
private readonly DbContextOptions<MyContext> _dbContextOptions;
public GenericRepository(DbContextOptions<MyContext> dbContextOptions)
{
_dbContextOptions = dbContextOptions;
}
public async Task<TEntity> Get(Expression<Func<TEntity, bool>> predicate, string code)
{
try
{
using (var db = new MyContext(_dbContextOptions))
{
using (var tr = db.Database.BeginTransaction(
IsolationLevel.ReadUncommitted))
{
var entity = await db.Set<TEntity>().AsNoTracking()
.FirstAsync(predicate);
tr.Commit();
return entity;
}
}
}
catch (Exception e)
{
throw new Exception("Error on getting entity by code: {code}");
}
}
}
公共类DealTypeRepository:GenericRepository,IDealTypeRepository
{
公共DealTypeRepository(DbContextOptions DbContextOptions)
:base(dbContextOptions)
{
}
}
公共类GenericRepository,其中tenty:类
{
私有只读DbContextOptions_DbContextOptions;
公共通用存储库(DbContextOptions DbContextOptions)
{
_dbContextOptions=dbContextOptions;
}
公共异步任务Get(表达式谓词、字符串代码)
{
尝试
{
使用(var db=newmycontext(_dbContextOptions))
{
使用(var tr=db.Database.BeginTransaction(
IsolationLevel.ReadUncommitted)
{
var entity=await db.Set().AsNoTracking()
.FirstAsync(谓词);
tr.Commit();
返回实体;
}
}
}
捕获(例外e)
{
抛出新异常(“按代码获取实体时出错:{code}”);
}
}
}
您能指导我如何检索CacheKeys类所需的属性以编写泛型方法吗?我想这很容易通过反思来实现
更新:
我不确定是否必须尝试一种通用方法,因为每个实体都有自己名称的Id属性(例如,IdDealType代表dealType,IdCurrency代表currency)在开始之前:此解决方案假设您的所有实体都遵循您在示例代码中显示的命名约定 首先,如果您有一个专用于此服务的存储库会更好,这样就可以按任何实体类型进行查询。在这里,您可以使用约定来获取这些属性名称,并且可以使用来查询它们。由于您的所有查询似乎都在“代码”列上,我们还可以简化该repo方法的参数
public class ParamRepository : IParamRepository
{
private readonly DbContextOptions<MyContext> _dbContextOptions;
public ParamRepository(DbContextOptions<MyContext> dbContextOptions)
{
_dbContextOptions = dbContextOptions;
}
public async Task<(int id, string name)> GetParamsByCode<TEntity>(string code) where TEntity : class
{
string entityName = typeof(TEntity).Name;
string idProp = $"Id{entityName}";
string nameProp = $"{entityName}Name";
try
{
using (var db = new MyContext(_dbContextOptions))
{
var entity = await db.Set<TEntity>().AsNoTracking()
.Where(p => EF.Property<string>(p, "Code") == code)
.Select(p => new { Id = EF.Property<int>(p, idProp), Name = EF.Property<string>(p, nameProp)})
.FirstAsync();
return (id: entity.Id, name: entity.Name);
}
}
catch (Exception e)
{
throw new Exception("Error on getting entity by code: {code}");
}
}
}
public类ParamRepository:IParamRepository
{
私有只读DbContextOptions_DbContextOptions;
公共参数存储库(DbContextOptions DbContextOptions)
{
_dbContextOptions=dbContextOptions;
}
公共异步任务GetParamsByCode(字符串代码),其中tenty:class
{
字符串entityName=typeof(tenty).Name;
字符串idProp=$“Id{entityName}”;
字符串nameProp=$“{entityName}Name”;
尝试
{
使用(var db=newmycontext(_dbContextOptions))
{
var entity=await db.Set().AsNoTracking()
其中(p=>EF.Property(p,“代码”)==Code)
.Select(p=>new{Id=EF.Property(p,idProp),Name=EF.Property(p,nameProp)})
.FirstAsync();
返回(id:entity.id,name:entity.name);
}
}
捕获(例外e)
{
抛出新异常(“按代码获取实体时出错:{code}”);
}
}
}
您还需要根据约定重构要创建的缓存键:
public static class CacheKeys
{
public static string GetIdKey<TEntity>() => $"_Id{typeof(TEntity).Name}";
public static string GetNameKey<TEntity>() => $"_{typeof(TEntity).Name}Name";
}
公共静态类缓存键
{
公共静态字符串GetIdKey()=>$“_Id{typeof(TEntity).Name}”;
公共静态字符串GetNameKey()=>$“{typeof(tenty).Name}Name”;
}
然后,在GetParamsService上变得简单:
public class GetParamsService
{
private readonly IMemoryCache _cache;
private readonly MemoryCacheEntryOptions _cacheOptions;
private readonly IParamRepository _paramRepository;
public GetParamsService(IMemoryCache memoryCache,
IParamRepository paramRepository)
{
_cache = memoryCache;
_cacheOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromHours(2));
_paramRepository = paramRepository;
}
public async Task<(int id, string name)> GetParams<TEntity>(string code) where TEntity : class
{
string cacheIdKey = CacheKeys.GetIdKey<TEntity>();
string cacheNameKey = CacheKeys.GetNameKey<TEntity>();
if (!_cache.TryGetValue(cacheIdKey, out int cacheId)
| !_cache.TryGetValue(cacheNameKey, out string cacheName))
{
var param = await _paramRepository.GetParamsByCode<TEntity>(code);
cacheId = param.id;
cacheName = param.name;
_cache.Set(cacheIdKey, cacheId, _cacheOptions);
_cache.Set(cacheNameKey, cacheName, _cacheOptions);
}
return (cacheId, cacheName);
}
}
公共类GetParamsService
{
专用只读IMemoryCache\u缓存;
专用只读存储器CacheEntryOptions\u cacheOptions;
专用只读IParamRepository\u paramRepository;
公共GetParamsService(IMemoryCache memoryCache,
IParamRepository(存储库)
{
_cache=memoryCache;
_cacheOptions=newmemorycacheentryoptions()
.SetSlidingExpiration(TimeSpan.FromHours(2));
_paramRepository=paramRepository;
}
公共异步任务GetParams(字符串代码),其中tenty:class
{
字符串cacheIdKey=CacheKeys.GetIdKey();
字符串cacheNameKey=CacheKeys.GetNameKey();
if(!\u cache.TryGetValue(cacheIdKey,out int cacheId)
|!\u cache.TryGetValue(cacheNameKey,out string cacheName))
{
var param=await_paramRepository.GetParamsByCode(代码);
cacheId=param.id;
cacheName=param.name;
_Set(cacheIdKey,cacheId,_cacheOptions);
_Set(cacheNameKey、cacheName、\u cacheOptions);
}
返回(cacheId、cacheName);
}
}
这是.NET Core,对吗?是的,这是.NET Core,非常好,但我得到一个错误:EF.Property方法只能在LINQ查询中使用。我使用2.1.1 EF核心。这个查询正在运行:var entity=await db.Set().AsNoTracking().Where(p=>EF.Property(p,“Code”)==Code)。选择(p=>new{Id=EF.Property(p,idProp),Name=EF.Property(p,nameProp)}).FirstAsync();对不起,我不明白。你的回答中的问题给了我一个错误。所以,我对您的查询做了一点修改(我在早期的评论中写了它),它工作得很好。其他事情都很好。非常感谢你们的努力,我现在对如何编写泛型方法有了更好的理解。当然,没问题!我将更改我的答案,以匹配您评论中的查询。
public class GetParamsService
{
private readonly IMemoryCache _cache;
private readonly MemoryCacheEntryOptions _cacheOptions;
private readonly IParamRepository _paramRepository;
public GetParamsService(IMemoryCache memoryCache,
IParamRepository paramRepository)
{
_cache = memoryCache;
_cacheOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromHours(2));
_paramRepository = paramRepository;
}
public async Task<(int id, string name)> GetParams<TEntity>(string code) where TEntity : class
{
string cacheIdKey = CacheKeys.GetIdKey<TEntity>();
string cacheNameKey = CacheKeys.GetNameKey<TEntity>();
if (!_cache.TryGetValue(cacheIdKey, out int cacheId)
| !_cache.TryGetValue(cacheNameKey, out string cacheName))
{
var param = await _paramRepository.GetParamsByCode<TEntity>(code);
cacheId = param.id;
cacheName = param.name;
_cache.Set(cacheIdKey, cacheId, _cacheOptions);
_cache.Set(cacheNameKey, cacheName, _cacheOptions);
}
return (cacheId, cacheName);
}
}