c# - 实体框架 6 -> 具有多个键的通用 DbSet.Find 方法
问题描述
我正在编写一个应用程序,我们在其中调用 20 多个 API 来使用实体框架在我们的数据库中添加或更新值。模型可以具有在 1-6 个属性之间变化的键。我已经为 Add 或 Update 编写了一个通用方法以避免重复代码,但我坚持DbSet.Find()
使用几个键动态调用。如果每个模型都具有相同数量的键,那将不是问题,但不幸的是,情况并非如此。
示例模型:
public class TPClassification
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Classifications ClassificationId { get; set; }
[MaxLength(100)]
public string Description { get; set; }
public bool IsCyclical { get; set; }
[MaxLength(400)]
public string Comment { get; set; }
}
public class TPFeeCalculation
{
[Key, Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[MaxLength(15)]
public string BusinessSystemId { get; set; }
[Key, Column(Order = 1)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CaseId { get; set; }
[ForeignKey("BusinessSystemId,CaseId")]
public virtual TPCase TPCase { get; set; }
[Key, Column(Order = 2)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[MaxLength(5)]
public string Action { get; set; }
[Key, Column(Order = 3)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Cycle { get; set; }
[ForeignKey("BusinessSystemId,CaseId,Action,Cycle")]
public virtual TPRenewalCycle TPRenewalCycle { get; set; }
[Key, Column(Order = 4)]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int RateNo { get; set; }
[MaxLength(100)]
public string RateDescription { get; set; }
}
API 调用:
public ICollection<TPFeeCalculation> GetFeeCalculation(string businessSystemId, int caseId)
{
var url = $"/api/feecalculations/{businessSystemId}/{caseId}";
var result = GetRequest<ICollection<TPFeeCalculation>>(url);
return result;
}
public ICollection<TPClassification> GetClassifications()
{
var url = $"/api/classifications/";
var result = GetRequest<ICollection<TPClassification>>(url);
return result;
}
AddOrUpdate 方法:
// All methods could be called like this but it will result in a lof of code that is nearly duplicated
//internal void AddOrUpdateClassifications()
//{
// var result = _IntegrationApiService.GetClassifications();
//
// //foreach (var value in result)
// //{
// // try
// // {
// // var current = _DbContext.Classifications.Find(value.ClassificationId);
// // if (current == null)
// // {
// // _DbContext.Classifications.Add(value);
// // }
// // else
// // {
// // _DbContext.Entry(current).CurrentValues.SetValues(value);
// // }
// // }
// // catch (Exception e)
// // {
// // throw;
// // }
// //}
// //_DbContext.SaveChanges();
//}
internal void AddOrUpdateClassifications()
{
var result = _IntegrationApiService.GetClassifications();
GenericAddOrUpdate(result, "ClassificationId");
}
internal void AddOrUpdateFeeCalculations(string businessSystemId, int caseId)
{
var result = _IntegrationApiService.GetFeeCalculation(businessSystemId, caseId);
//This does not work
//GenericAddOrUpdate(result, "BusinessSystemId", "CaseId", "Action", "Cycle", "RateNo");
}
private void GenericAddOrUpdate<T>(ICollection<T> values, params string[] keyValues) where T : class
{
foreach (var value in values)
{
try
{
var keyList = new List<object>();
foreach (var keyValue in keyValues)
{
var propertyInfo = value.GetType().GetProperty(keyValue);
var propertyValue = propertyInfo.GetValue(value);
keyList.Add(propertyValue);
}
var someDbSet = _DbContext.Set(typeof(T));
//I need to add all the values from keyList here. I can't add the list directly since I will get the error below. Example with keyList[0] to show working code
//The specified parameter type 'System.Collections.Generic.List`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, //PublicKeyToken=b77a5c561934e089]]' is not valid. Only scalar types, such as System.Int32, System.Decimal, System.DateTime, and System.Guid, are supported.
var current = someDbSet.Find(keyList[0]);
if (current == null)
{
someDbSet.Add(value);
}
else
{
_DbContext.Entry(current).CurrentValues.SetValues(value);
}
}
catch (Exception e)
{
throw;
}
}
_DbContext.SaveChanges();
}
解决方案
推荐阅读
- javascript - 在沙盒 iframe 中使用常见的 JS 库
- javascript - 单击按钮时JS .click()不起作用
- android - 自定义 RecyclerViewAdapter 内的 MapView
- c# - c#正则表达式几个带逗号的数字
- vcf-vcard - xmlstarlet Fritzbox XML 电话簿到 VCARD
- sql - 如何提高此查询的性能
- javascript - (未经授权)从 localhost 请求时 - “node testRequest.js”时没有错误
- django - 如果 Django 模型中的函数调用包含 db 查询而其他函数工作正常,为什么它不刷新值?
- java - 如何使用 Spring-Boot 清除 @Async 任务的所有已完成的 Future 结果?
- python - bigquery python中的流式插入