.NET 文件系统(五)--主表主键获取,获取子表类型,主表的存储与子表验证实现
作者:互联网
FileDownLoadSystem.Core
BaseService改造
Extensions文件夹新增扩展类:EntityPropertiesExtensions
EntityPropertiesExtensions
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace FileDownLoadSystem.Core.Extensions
{
public static class EntityPropertiesExtensions
{
public static PropertyInfo GetKeyProperty(this Type entity)
{
return entity.GetProperties().GetKeyProperty();
}
public static PropertyInfo GetKeyProperty(this IEnumerable<PropertyInfo> propertyInfos)
{
return propertyInfos.Where(c => c.IsKey()).FirstOrDefault();
}
public static bool IsKey(this PropertyInfo property)
{
return property.GetCustomAttributes(typeof(KeyAttribute), false).Any();
}
}
}
拆分这么细的原因是为了考虑到以后会复用,所以拆成了三个方法
获取子表类型
在Entity层增加一个文件夹AttributeManager
新增一个类:EntityAttribute
EntityAttribute
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace FileDownLoadSystem.Entity.AttributeManager
{
public class EntityAttribute : Attribute
{
/// <summary>
/// 当前表的真实名称
/// </summary>
/// <value></value>
public string TableName { get; set; }
/// <summary>
/// 表的中文名称
/// </summary>
/// <value></value>
public string TableChineseName { get; set; }
/// <summary>
/// 明细表
/// </summary>
/// <value></value>
public Type[] DetailTable { get; set; }
}
}
BaseService 新增Update方法,改造如下
BaseService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using FileDownLoadSystem.Core.Enums;
using FileDownLoadSystem.Core.Extensions;
using FileDownLoadSystem.Core.Utility;
using FileDownLoadSystem.Entity;
using FileDownLoadSystem.Entity.AttributeManager;
using FileDownLoadSystem.Entity.Core;
using Microsoft.EntityFrameworkCore;
namespace FileDownLoadSystem.Core.BaseProvider
{
public class BaseService<TModel, TRepository>
where TModel : BaseModel
where TRepository : IRepository<TModel>
{
protected readonly TRepository _repository;
private WebResponseContent _responseContent;
public BaseService(TRepository repository)
{
this._repository = repository;
_responseContent = new(true);
}
public TModel FindFirst(Expression<Func<TModel, bool>> predicate,
Expression<Func<TModel, Dictionary<object, QueryOrderBy>>> orderBy = null)
{
return _repository.FindFirst(predicate, orderBy);
}
public virtual WebResponseContent AddEntity(TModel entity)
{
return Add<TModel>(entity, null);
}
public WebResponseContent Add<TDetail>(TModel entity, List<TDetail> list = null)
where TDetail : class
{
_repository.Insert(entity);
// 保存明细
if (list != null && list.Count > 0)
{
list.ForEach(item =>
{
//开启对当前对象的跟踪
_repository.DbContext.Entry<TDetail>(item).State = EntityState.Added;
});
_repository.DbContext.SaveChanges();
}
_responseContent.OK(ResponseType.SaveSuccess);
return _responseContent;
}
public WebResponseContent UpdateEntity<TDetail>(SaveModel saveModel)
where TDetail : BaseModel
{
var datailList = saveModel.DetailData.DicToList<TDetail>();
return default;
}
public WebResponse Update(SaveModel saveModel)
{
//获取主表类型
var type = typeof(TModel);
//主表主键的获取
var mainKeyProperty = type.GetKeyProperty();
Type detailType = null;
if (saveModel.DetailData != null)
{
saveModel.DetailData = saveModel.DetailData == null
? new List<Dictionary<string, object>>()
: saveModel.DetailData.Where(x => x.Count > 0).ToList();
//获取主表特性里的明细类型
detailType = GetRealDetailType();
}
return default;
}
private Type? GetRealDetailType()
{
return typeof(TModel).GetCustomAttribute<EntityAttribute>()?.DetailTable?[0];
}
}
}
主要目的:为了获取主表特性里的明细类型
上端调用方式为:
WeatherForecastController
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using FileDownLoadSystem.Entity.Core;
using FileDownLoadSystem.Entity.FileInfo;
using FileDownLoadSystem.System.IRepositories;
using FileDownLoadSystem.System.IServices;
using Microsoft.AspNetCore.Mvc;
namespace FileDownLoadSystem.API.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
private readonly IFileService _fileRepository;
public WeatherForecastController(ILogger<WeatherForecastController> logger, IFileService fileRepository)
{
this._fileRepository = fileRepository;
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
var result = _fileRepository.Update(new SaveModel()
{
MainData = new Dictionary<string, object>()
{
{"Id",1},
{"PublicDate",DateTime.Now}
},
DetailData = new List<Dictionary<string, object>>()
{
new Dictionary<string,object>(){
{"FileId",1},
{"PackageUrl","http://TreeSet.com"}
}
}
});
//1
var res = _fileRepository.UpdateEntity<Files>(new SaveModel()
{
DetailData = new List<Dictionary<string, object>>()
{
new Dictionary<string,object>(){
{"Id",1}
}
}
});
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}
主表的存储
BaseService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using FileDownLoadSystem.Core.Enums;
using FileDownLoadSystem.Core.Extensions;
using FileDownLoadSystem.Core.Utility;
using FileDownLoadSystem.Entity;
using FileDownLoadSystem.Entity.AttributeManager;
using FileDownLoadSystem.Entity.Core;
using Microsoft.EntityFrameworkCore;
namespace FileDownLoadSystem.Core.BaseProvider
{
public class BaseService<TModel, TRepository>
where TModel : BaseModel
where TRepository : IRepository<TModel>
{
protected readonly TRepository _repository;
private WebResponseContent _responseContent;
public BaseService(TRepository repository)
{
this._repository = repository;
_responseContent = new(true);
}
public TModel FindFirst(Expression<Func<TModel, bool>> predicate,
Expression<Func<TModel, Dictionary<object, QueryOrderBy>>> orderBy = null)
{
return _repository.FindFirst(predicate, orderBy);
}
public virtual WebResponseContent AddEntity(TModel entity)
{
return Add<TModel>(entity, null);
}
public WebResponseContent Add<TDetail>(TModel entity, List<TDetail> list = null)
where TDetail : class
{
_repository.Insert(entity);
// 保存明细
if (list != null && list.Count > 0)
{
list.ForEach(item =>
{
//开启对当前对象的跟踪
_repository.DbContext.Entry<TDetail>(item).State = EntityState.Added;
});
_repository.DbContext.SaveChanges();
}
_responseContent.OK(ResponseType.SaveSuccess);
return _responseContent;
}
public WebResponseContent UpdateEntity<TDetail>(SaveModel saveModel)
where TDetail : BaseModel
{
var datailList = saveModel.DetailData.DicToList<TDetail>();
return default;
}
public WebResponseContent Update(SaveModel saveModel)
{
//获取主表类型
var type = typeof(TModel);
//主表主键的获取
var mainKeyProperty = type.GetKeyProperty();
Type detailType = null;
if (saveModel.DetailData != null)
{
saveModel.DetailData = saveModel.DetailData == null
? new List<Dictionary<string, object>>()
: saveModel.DetailData.Where(x => x.Count > 0).ToList();
//获取主表特性里的明细类型
detailType = GetRealDetailType();
}
if (mainKeyProperty == null
|| !saveModel.MainData.ContainsKey(mainKeyProperty.Name)
|| saveModel.MainData[mainKeyProperty.Name] == null)
{
return _responseContent.Error(ResponseType.NoKey);
}
if (detailType == null)
{
TModel mainEntity = saveModel.MainData.DicToEntity<TModel>();
_repository.Update(mainEntity);
_responseContent.OK(ResponseType.SaveSuccess);
_responseContent.Data = new { data = mainEntity };
return _responseContent;
}
return default;
}
private Type? GetRealDetailType()
{
return typeof(TModel).GetCustomAttribute<EntityAttribute>()?.DetailTable?[0];
}
}
}
上端调用修改:
WeatherForecastController
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using FileDownLoadSystem.Core.Utility;
using FileDownLoadSystem.Entity.Core;
using FileDownLoadSystem.Entity.FileInfo;
using FileDownLoadSystem.System.IRepositories;
using FileDownLoadSystem.System.IServices;
using Microsoft.AspNetCore.Mvc;
namespace FileDownLoadSystem.API.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
private readonly IFileService _fileRepository;
public WeatherForecastController(ILogger<WeatherForecastController> logger, IFileService fileRepository)
{
this._fileRepository = fileRepository;
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public WebResponseContent Get()
{
var result = _fileRepository.Update(new SaveModel()
{
MainData = new Dictionary<string, object>()
{
{"PublicDate",DateTime.Now}
},
// DetailData = new List<Dictionary<string, object>>()
// {
// new Dictionary<string,object>(){
// {"FileId",1},
// {"PackageUrl","http://TreeSet.com"}
// }
// }
});
//1
// var res = _fileRepository.UpdateEntity<Files>(new SaveModel()
// {
// DetailData = new List<Dictionary<string, object>>()
// {
// new Dictionary<string,object>(){
// {"Id",1}
// }
// }
// });
return result;
}
}
}
子表验证实现
改造BaseService
BaseService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using FileDownLoadSystem.Core.Enums;
using FileDownLoadSystem.Core.Extensions;
using FileDownLoadSystem.Core.Utility;
using FileDownLoadSystem.Entity;
using FileDownLoadSystem.Entity.AttributeManager;
using FileDownLoadSystem.Entity.Core;
using Microsoft.EntityFrameworkCore;
namespace FileDownLoadSystem.Core.BaseProvider
{
public class BaseService<TModel, TRepository>
where TModel : BaseModel
where TRepository : IRepository<TModel>
{
protected readonly TRepository _repository;
private WebResponseContent _responseContent;
public BaseService(TRepository repository)
{
this._repository = repository;
_responseContent = new(true);
}
public TModel FindFirst(Expression<Func<TModel, bool>> predicate,
Expression<Func<TModel, Dictionary<object, QueryOrderBy>>> orderBy = null)
{
return _repository.FindFirst(predicate, orderBy);
}
public virtual WebResponseContent AddEntity(TModel entity)
{
return Add<TModel>(entity, null);
}
public WebResponseContent Add<TDetail>(TModel entity, List<TDetail> list = null)
where TDetail : class
{
_repository.Insert(entity);
// 保存明细
if (list != null && list.Count > 0)
{
list.ForEach(item =>
{
//开启对当前对象的跟踪
_repository.DbContext.Entry<TDetail>(item).State = EntityState.Added;
});
_repository.DbContext.SaveChanges();
}
_responseContent.OK(ResponseType.SaveSuccess);
return _responseContent;
}
public WebResponseContent UpdateEntity<TDetail>(
SaveModel saveModel,
PropertyInfo mainKeyProperty,
PropertyInfo detailKeyInfo,
object keyDefaultVal)
where TDetail : BaseModel
{
var datailList = saveModel.DetailData.DicToList<TDetail>();
return default;
}
public WebResponseContent Update(SaveModel saveModel)
{
//获取主表类型
var type = typeof(TModel);
//主表主键的获取
var mainKeyProperty = type.GetKeyProperty();
Type detailType = null;
if (saveModel.DetailData != null)
{
saveModel.DetailData = saveModel.DetailData == null
? new List<Dictionary<string, object>>()
: saveModel.DetailData.Where(x => x.Count > 0).ToList();
//获取主表特性里的明细类型
detailType = GetRealDetailType();
}
if (mainKeyProperty == null
|| !saveModel.MainData.ContainsKey(mainKeyProperty.Name)
|| saveModel.MainData[mainKeyProperty.Name] == null)
{
return _responseContent.Error(ResponseType.NoKey);
}
if (detailType == null)
{
TModel mainEntity = saveModel.MainData.DicToEntity<TModel>();
_repository.Update(mainEntity);
_responseContent.OK(ResponseType.SaveSuccess);
_responseContent.Data = new { data = mainEntity };
return _responseContent;
}
var foreignKeyName = typeof(TModel).GetCustomAttribute<EntityAttribute>()?.ForeignKeyName;
saveModel.DetailData = saveModel.DetailData.Where(x => x.Count > 0).ToList();
PropertyInfo detailKeyInfo = detailType.GetKeyProperty();
object keyDefaultVal = mainKeyProperty.PropertyType.Assembly.CreateInstance(mainKeyProperty.PropertyType.FullName);
foreach (var dic in saveModel.DetailData)
{
object detailKeyDefaultVal = mainKeyProperty.PropertyType.Assembly.CreateInstance(detailKeyInfo.PropertyType.FullName);
if (dic[detailKeyInfo.Name] == null)
{
return _responseContent.Error(ResponseType.NoKey);
}
string detailKeyValue = dic[detailKeyInfo.Name].ToString();
//判断子表的主键值是否正确
if (detailKeyValue != detailKeyDefaultVal.ToString()
|| !dic.ContainsKey(foreignKeyName)
|| dic[foreignKeyName] != null
|| dic[foreignKeyName].ToString() == keyDefaultVal.ToString())
{
return _responseContent.Error($"{foreignKeyName} 是必须的");
}
}
return this.GetType().GetMethod("UpdateEntity")
.MakeGenericMethod(detailType)
.Invoke(this, new object[] { saveModel, mainKeyProperty, detailKeyInfo, keyDefaultVal })
as WebResponseContent;
}
private Type? GetRealDetailType()
{
return typeof(TModel).GetCustomAttribute<EntityAttribute>()?.DetailTable?[0];
}
}
}
标签:return,FileDownLoadSystem,System,saveModel,获取,using,子表,主表,public 来源: https://www.cnblogs.com/rookiewang/p/16684794.html