其他分享
首页 > 其他分享> > .NET 文件系统(五)--主表主键获取,获取子表类型,主表的存储与子表验证实现

.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