c# 技术点总结
sqlsuagr查询优化 查询耗时长的问题
/// <summary> /// 【推荐使用这个】根据主键ID数组数据查询 /// </summary> /// <param name="Id"></param> /// <returns></returns> public async Task<List<表>> GetRangeAsync(long[] id) { Expressionable<表> exp = new Expressionable<表>(); foreach (var item in id) { exp.Or(it => it.Id == item); } //使用构造好的表达式 return await Context.Queryable<表>().Where(exp.ToExpression()).ToListAsync(); } /// <summary> /// 根据主键ID数组数据查询 数据量超过30W 查询速度最少2.5秒 转换成的SQL为如下【 SELECT *FROM 表 WHERE ( CAST(`Id` AS SIGNED) IN (15008372))】 /// </summary> /// <param name="Id"></param> /// <returns></returns> public async Task<List<OrderChargeEntity>> GetRangeAsync(int[] id) { return await Context.Queryable<表>().Where(it => id.Contains(Convert.ToInt32(it.Id))).ToListAsync(); }
//两个LIst 去重合并, 用Union无效
原因是:List存在内存里面是引用类型 Union比较的是引用地址 不像值类型一样直接比较值
所以Union要重写
returnList.InvoiceCompanyNoticeOutputList = invoiceFollowUpDataList.Union(invoiceCompanyNoticeInputList).ToList(); public class InvoiceCompanyNoticeOutputs { /// <summary> /// 所属公司ID /// </summary> public int belongCompanyId { get; set; } /// <summary> /// 结算公司ID /// </summary> public int SettlementCompanyId { get; set; } /// <summary> /// 结算公司名称 /// </summary> public string SettlementCompanyCnName { get; set; } /// <summary> /// 公司性质 /// </summary> public CompanyQualityEnum CompanyQualityEnum { get; set; } /// <summary> /// 0禁用 1启用 /// </summary> public InvoiceFollowUpStatusEnum Status { get; set; } = InvoiceFollowUpStatusEnum.启用; /// <summary> /// 重写union 值类型比较的是引用地址 /// </summary> /// <returns></returns> public override int GetHashCode() { return HashCode.Combine(belongCompanyId, SettlementCompanyId, SettlementCompanyCnName); } public override bool Equals(object obj) { if (obj == null) return false; if (obj is InvoiceCompanyNoticeOutputs input) { return GetHashCode() == input.GetHashCode(); } return false; } }
//深拷贝对象
/// <summary> /// 深拷贝对象:循环List是直接改变当前对象的值,所以如果需要改变值且不动到当前list需要深拷贝, 因为是引用类型最终都是指向一个内存地址 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="original"></param> /// <returns></returns> private static T DeepCopy<T>(T original) { return (T)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(original), original.GetType()); }
//求两个List<实体>之间的差集
List<A> A = new List<A>(); List<B> B= new List<B>(); public class AEquality : IEqualityComparer<A> { public bool Equals(A x, A y) { return x.Id == y.Id && x.Name == y.Name } public int GetHashCode(A obj) { return (obj == null) ? 0 : obj.ToString().GetHashCode(); } } var except = A.Except(B, new AEquality()).ToList(); if (except.Count() > 0) throw JNPFException.Oh("存在差集"); //C类是A类的子类 可直接使用AEquality 如下 var except = C.Except(B, new AEquality()).ToList(); if (except.Count() > 0) throw JNPFException.Oh("存在差集");
c# List的groupBy和distinct区别
distinct是去重
List的groupBy得到的结果是。已当前的KEY分组 符合当前key 就加在里面
linq在数据分组时,不会像数据库group by那样,表面上只返回group by后的一条数据(会去重),而是根据要分组的条件,把数据汇聚成一个字典,字典的键为分组的条件,字典的值是一个数组,包含所有满足分组条件的数据。
/// listOutputs 为数据库查到的数据,然后进行复杂排序 List<SettleChargeDetailListOutput> ListOrderby = new List<SettleChargeDetailListOutput>(); var listGroupBy = listOutputs.GroupBy(x => new{ x.ChargeDetailId }); foreach (var item in listGroupBy) { // var tmp = item.OrderByDescending(x =>x.SettleChargeUpdateTime); ListOrderby.AddRange(tmp); } reutrn ListOrderby
var entityGroup = entityList.GroupBy(x => new { x.OrderChargeId}). Select(group => new TSettleChargeDetailEntity { OrderChargeId = group.Key.OrderChargeId, Amount = entityList.Where(x => x.OrderChargeId == group.Key.OrderChargeId).Sum(x => x.Amount), }).ToList(); var entityGroup = entityList.GroupBy(x => new { x.OrderChargeId,x.WriteoffRecordId }). Select(group => new TSettleChargeDetailEntity { OrderChargeId = group.Key.OrderChargeId, WriteoffRecordId = group.Key.WriteoffRecordId, Amount = entityList.Where(x => x.OrderChargeId == group.Key.OrderChargeId).Sum(x => x.Amount), }).ToList();
sql查询优化,查询出来进行判断赋值,组装数据返回给前端
财务标记 精度计算 四舍五入
/// <summary> /// 默认是ToEven,如果设置为AwayFromZero,会将中间值舍入最接近零的数字,在正数里可以实现四舍五入, /// 但是如果在负数里就会出现四舍六入,若要实现正数负数都四舍五入,可以在使用Math.Round方法前先判断是否为负数,若为负数,取绝对值,等四舍五入之后再转成负数。 /// </summary> /// <param name="d"></param> /// <param name="decimals">取:1=AwayFromZero</param> /// <returns></returns> private decimal Round(decimal d, int decimals=1) { decimal sign = 1; decimal result = d; if (d < 0) { sign = -1; result *= sign; } result = Math.Round(result, decimals, MidpointRounding.AwayFromZero); result *= sign; return result; }
Auto忽略源属性 或者目标属性
链接地址: 我已经更新了Can Gencer的扩展,不会覆盖任何现有的地图. public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression) { var sourceType = typeof (TSource); var destinationType = typeof (TDestination); var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType)); foreach (var property in existingMaps.GetUnmappedPropertyNames()) { expression.ForMember(property, opt => opt.Ignore()); } return expression; } 用法: Mapper.CreateMap<SourceType, DestinationType>() .ForMember(prop => x.Property, opt => opt.MapFrom(src => src.OtherProperty)) .IgnoreAllNonExisting(); 对于AutoMapper 5+版本,只需将`Mapper.GetAllTypeMaps()`替换为`Mapper.Configuration.GetAllTypeMaps()`.这是参考github.com/AutoMapper/AutoMapper/issues/1252 (14认同) 对于阅读此内容的新人.这个答案适用于AutoMapper 2,在编写本评论时,我们的版本为6.这是一个黑客,更简洁的方法是使用MemberList枚举.请参阅Github问题1839和更好的解决方案.例如:https://stithoverflow.com/a/31182390 (5认同) +1,感谢您发布此解决方案.当我在http://goo.gl/rG7SL中使用解决方案时,花了我几个小时来计算奇怪的错误,直到我再次偶然发现这篇文章. (4认同) 我推荐Yohanb的方法.有一些极端情况,这似乎不起作用. (3认同) 可以在AutoMapper 4.2中完成吗?(不推荐使用`Mapper.GetAllTypeMaps()`) (3认同) 有道理,似乎是一个更强大的解决方案,更新我的答案指向你的.不知道方法"GetUnmappedPropertyNames":) (2认同) 适用于静态Mapper类.当您通过IoC配置AutoMapper时,您需要获取IConfigurationProvider以获取所有类型的地图. (2认同) 218 根据我的理解,问题是目标上的字段在源中没有映射字段,这就是为什么要查找忽略那些非映射目标字段的方法. 您可以简单地使用,而不是实现和使用这些扩展方法 Mapper.CreateMap<destinationModel, sourceModel>(MemberList.Source); 现在,automapper知道它只需要验证所有源字段是否已映射,而不是相反. 您还可以使用: Mapper.CreateMap<destinationModel, sourceModel>(MemberList.Destination); 对于后来的任何人来说,这是5.0的正确答案 (56认同) 这个答案应该有更多的赞成,甚至可能被标记为答案.它解决了我的问题,同样`MemberList.Destination`将解决操作问题. (10认同) 看起来很漂亮,但没有为我工作..我尝试了源和目的地,但它一直在抱怨缺少地图的相同属性对象 (3认同) 使用 6.0.2 并且这不起作用。任何未从目标映射到源的属性,都使用空值和 0 覆盖源中的属性。此外,代码并没有明确说明您在做什么,尤其是当您在团队中工作时。这就是为什么我非常不喜欢这段代码,以及为什么我更喜欢像建议的答案“IgnoreAllNonExisting”这样的选择词 (3认同) 83 我已经能够通过以下方式实现这一目标: Mapper.CreateMap<SourceType, DestinationType>().ForAllMembers(opt => opt.Ignore()); Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 1 here*/); Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 2 here*/); ... 注意:我使用的是AutoMapper v.2.0. 非常感谢!它就像一个魅力.我首先尝试将调用链接起来,但ForAllMembers只返回void :(.之前的IgnoreAll可以稍后修改并不明显. (4认同) 我也不喜欢这种方式..如果你有50个成员,并且你想忽略25 ..那么如果你仍然要忽略25个成员那么自动化的重点是什么.如果名称匹配,并且存在不匹配的属性..为什么不明确告诉automapper在未映射的属性上不匹配并通过传递所有键入? (4认同) Can*_*cer 82 这是我编写的一种扩展方法,它忽略了目标上的所有非现有属性.不确定它是否仍然有用,因为问题超过两年,但我遇到了同样的问题,不得不添加大量的手动忽略调用. public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination> (this IMappingExpression<TSource, TDestination> expression) { var flags = BindingFlags.Public | BindingFlags.Instance; var sourceType = typeof (TSource); var destinationProperties = typeof (TDestination).GetProperties(flags); foreach (var property in destinationProperties) { if (sourceType.GetProperty(property.Name, flags) == null) { expression.ForMember(property.Name, opt => opt.Ignore()); } } return expression; } 用法: Mapper.CreateMap<SourceType, DestinationType>() .IgnoreAllNonExisting(); 更新:如果您有自定义映射,显然这不能正常工作,因为它会覆盖它们.我想如果先调用IgnoreAllNonExisting然后再调用自定义映射,它仍然可以工作. schdr有一个解决方案(作为这个问题的答案),用于Mapper.GetAllTypeMaps()找出哪些属性未映射并自动忽略它们.对我来说似乎是一个更强大的解决方案. 这个方法应该在autoMapper本机代码上!很好谢谢! (3认同) 谢谢!!我发现这非常方便.在我的情况下,单独忽略属性会破坏使用automapper的目的. (2认同) 仅供参考,吉米本人(AutoMapper的作者)在下面评论说,@ nazim的答案对于版本5+是正确的 (2认同) ajb*_*ven 63 AutoMapper的5.0.0-beta-1版本引入了ForAllOtherMembers扩展方法,因此您现在可以执行此操作: CreateMap<Source, Destination>() .ForMember(d => d.Text, o => o.MapFrom(s => s.Name)) .ForMember(d => d.Value, o => o.MapFrom(s => s.Id)) .ForAllOtherMembers(opts => opts.Ignore()); 请注意,显式映射每个属性都有一个优势,因为当您忘记映射属性时,您将永远不会出现静默映射失败的问题. 也许在你的情况下,忽略所有其他成员并添加一个TODO回来并在这个类的更改频率稳定下来之后使这些成员显然是明智的. 这个惊人了,直到第5版看我多少了-votes并试图回答这个问题......与Automapper治理什么问题不知道? (3认同) 您甚至可以将ForAllOtherMembers行放在最前面,并且一切正常,如果您具有某种基类配置,则很好。 (2认同) Ric*_*ard 43 从AutoMapper 5.0开始,.TypeMap属性IMappingExpression已经消失,这意味着4.2解决方案不再有效.我创建了一个使用原始功能但使用不同语法的解决方案: var config = new MapperConfiguration(cfg => { cfg.CreateMap<Src, Dest>(); cfg.IgnoreUnmapped(); // Ignores unmapped properties on all maps cfg.IgnoreUnmapped<Src, Dest>(); // Ignores unmapped properties on specific map }); // or add inside a profile public class MyProfile : Profile { this.IgnoreUnmapped(); CreateMap<MyType1, MyType2>(); } 执行: public static class MapperExtensions { private static void IgnoreUnmappedProperties(TypeMap map, IMappingExpression expr) { foreach (string propName in map.GetUnmappedPropertyNames()) { if (map.SourceType.GetProperty(propName) != null) { expr.ForSourceMember(propName, opt => opt.Ignore()); } if (map.DestinationType.GetProperty(propName) != null) { expr.ForMember(propName, opt => opt.Ignore()); } } } public static void IgnoreUnmapped(this IProfileExpression profile) { profile.ForAllMaps(IgnoreUnmappedProperties); } public static void IgnoreUnmapped(this IProfileExpression profile, Func<TypeMap, bool> filter) { profile.ForAllMaps((map, expr) => { if (filter(map)) { IgnoreUnmappedProperties(map, expr); } }); } public static void IgnoreUnmapped(this IProfileExpression profile, Type src, Type dest) { profile.IgnoreUnmapped((TypeMap map) => map.SourceType == src && map.DestinationType == dest); } public static void IgnoreUnmapped<TSrc, TDest>(this IProfileExpression profile) { profile.IgnoreUnmapped(typeof(TSrc), typeof(TDest)); } } 你如何在`Profile`中的链式`CreateMap <TSource,TDest>()`表达式中使用它? (3认同) 谢谢你.GetUnmappedPropertyNames方法返回源和目标上的所有未映射的属性名称,这似乎是在反向映射上中断,因此我必须对IgnoreUnmapped进行一些小的更改,以检查未映射的属性是否在源或目标上并忽略因此.这是一个演示问题和更新的小提琴:https://dotnetfiddle.net/vkRGJv (2认同) Ira*_*chi 17 问题问题已经有几年了,但是使用当前版本的AutoMapper(3.2.1),这种扩展方法对我来说似乎更干净: public static IMappingExpression<TSource, TDestination> IgnoreUnmappedProperties<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression) { var typeMap = Mapper.FindTypeMapFor<TSource, TDestination>(); if (typeMap != null) { foreach (var unmappedPropertyName in typeMap.GetUnmappedPropertyNames()) { expression.ForMember(unmappedPropertyName, opt => opt.Ignore()); } } return expression; } nic*_*k_w 16 对于那些谁正在使用的非静态API在4.2.0及以上版本,下面的扩展方法(发现这里的AutoMapperExtensions类)可用于: // from http://stackoverflow.com/questions/954480/automapper-ignore-the-rest/6474397#6474397 public static IMappingExpression IgnoreAllNonExisting(this IMappingExpression expression) { foreach(var property in expression.TypeMap.GetUnmappedPropertyNames()) { expression.ForMember(property, opt => opt.Ignore()); } return expression; } 这里重要的是,一旦删除静态API,代码Mapper.FindTypeMapFor将不再起作用,因此使用该expression.TypeMap字段. 从5.0开始,`expression.TypeMap`不再可用.这是[我的5.0解决方案](http://stackoverflow.com/a/38073718/163495) (7认同) 16 对于Automapper 5.0,您可以跳过所有未映射的属性 .ForAllOtherMembers(X => x.Ignore()); 在你的个人资料的最后. 例如: internal class AccountInfoEntityToAccountDtoProfile : Profile { public AccountInfoEntityToAccountDtoProfile() { CreateMap<AccountInfoEntity, AccountDto>() .ForMember(d => d.Id, e => e.MapFrom(s => s.BankAcctInfo.BankAcctFrom.AcctId)) .ForAllOtherMembers(x=>x.Ignore()); } } 在这种情况下,将仅解析输出对象的Id字段,将跳过所有其他字段.像魅力一样工作,似乎我们不再需要任何棘手的扩展! mrm*_*hal 10 我更新了Robert Schroeder对AutoMapper 4.2的回答.使用非静态映射器配置,我们不能使用Mapper.GetAllTypeMaps(),但是expression具有对所需的引用TypeMap: public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression) { foreach (var property in expression.TypeMap.GetUnmappedPropertyNames()) { expression.ForMember(property, opt => opt.Ignore()); } return expression; } Jim*_*ard 8 您希望如何指定忽略某些成员?是否有您想要应用的约定,基类或属性?一旦你开始明确指定所有映射的业务,我不确定你从AutoMapper中得到什么价值. 这不是问题的答案. (6认同) 如何只有一个可配置的值,你可以"忽略"所有不存在的字段. (2认同) 7 这似乎是一个古老的问题,但我想我会回答其他任何看起来像我的人. 我使用ConstructUsing,对象初始化器与ForAllMembers一起忽略例如 Mapper.CreateMap<Source, Target>() .ConstructUsing( f => new Target { PropVal1 = f.PropVal1, PropObj2 = Map<PropObj2Class>(f.PropObj2), PropVal4 = f.PropVal4 }) .ForAllMembers(a => a.Ignore()); 5 默认情况下,AutoMapper 使用目标类型来验证成员,但您可以使用MemberList.None选项跳过验证。 var configuration = new MapperConfiguration(cfg => cfg.CreateMap<Source2, Destination2>(MemberList.None); );
c#定义匿名List,c#定义LIst<匿名对象> c#定义List<元组> c#定义List<匿名实体>
//定义语法糖List<元祖> List<(int id,string code,decimal amount)> currencyList =new(); // List<Tuple<int, string>> aaa = new List<Tuple<int, string>>();list 元祖 if (1=1) { var list1 = foreach (var item in list1) { //aaa.Add(new Tuple<int, string>(1,"2")); currencyList.Add(new (item.id,item.code, item.amount )); } } else { var list2 =list foreach (var item in list2) { currencyList.Add(new ((int)item.id,item.code, item.amount)); } }
c# 金额增加千分符合分割,保留小数点2位
string Amount = $"{item.Amounts:#,##0.00}";
c# 金额转中文大写
/// <summary> /// 转中文大写 最大金额只能是 99999999.99 /// 不足位数的用x表示 如 100.50 xxxxx壹零零.伍零 /// </summary> /// <param name="money"></param> /// <returns></returns> public static string ConvertMoneyToCn(this decimal money) { if (money>99999999.99M) { throw new BusinessException(message: $"最大金额不能超过99999999.99"); } string placeholder = ""; int max = 8; var moneysrt = string.Format("{0:0.00}", money); int count = moneysrt.ToString().IndexOf('.'); //显示多少为 var gap = max - count; for (int i = 0; i < gap; i++) { placeholder += "X"; } string[] strs = new string[] { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; string str = moneysrt.ToString(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < str.Length; i++) { var a = str.Substring(i, 1); if (a!=".") { int num = Convert.ToInt32(str.Substring(i, 1)); sb.Append(strs[num]); } } return placeholder+sb.ToString(); }
比对2个集合
A是:原始合集,即相当于数据库中的集合 B是:目标集合,即相当于是界面操作的集合 假设A、B两个集合类型为 List<T>,其中 T 是要比较的对象类型,可以按照以下步骤进行对比: 1. 获取【更新集合】:找出 B 集合中在 A 集合中存在且属性值与 A 集合中不同的元素。 List<T> updatedItems = B.Where(b => A.Any(a => a.ID == b.ID && !a.Equals(b))).ToList(); 以上代码使用了 Where() 和 Any() 方法,其中 Where() 方法筛选出 B 集合中在 A 集合中存在且属性值与 A 集合中不同的元素,Any() 方法用于在 A 集合中查找是否存在元素的 ID 与 B 集合中的元素 ID 相同并且属性值不同。 2. 获取【插入集合】:找出 B 集合中在 A 集合中不存在的元素。 List<T> insertedItems = B.Where(b => !A.Any(a => a.ID == b.ID)).ToList(); 以上代码使用了 Where() 和 Any() 方法,只不过是在 A 集合中查找是否存在元素的 ID 与 B 集合中的元素 ID 相同。 3. 获取【删除集合】:找出 A 集合中在 B 集合中不存在的元素。 List<T> deletedItems = A.Where(a => !B.Any(b => b.ID == a.ID)).ToList(); 以上代码同样使用了 Where() 和 Any() 方法,在 B 集合中查找是否存在元素的 ID 与 A 集合中的元素 ID 相同。
本文来自博客园,作者:12不懂3,转载请注明原文链接:https://www.cnblogs.com/LZXX/p/16541298.html