c# 技术点总结

Linq扩展方法库:

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();
List,分组金额统计 多个key分组

 

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);
);
View Code

 

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 相同。

 

 

 

posted @ 2022-08-01 18:19  12不懂3  阅读(191)  评论(0编辑  收藏  举报
创作不易,请勿抄袭,欢迎转载!