别跟我谈EF抵抗并发,敢问你到底会不会用EntityFramework

前言

一直以来写的博文都是比较温婉型的博文,今天这篇博文算是一篇批判性博文,有问题欢迎探讨,如标题,你到底会不会用EntityFramework啊。

你到底会不会用EntityFramework啊

  面试过三年至六年的同行,作为过面试者到如今作为面试官也算是老大对我的信任,对来面试的面试者的任何一位同行绝没有刁难之意,若还装逼那就没有什么意义。我也基本不看面试者的项目经历,因为我个人觉得每个面试者所在公司所做项目都不一样,可能面试者项目所做的业务我一点都不知道,而我所关心的是项目当中所用到的技术,稍微看下了简历让面试者简单做个自我介绍,这算是基本流程吧。然后直接问面试者最擅长的技术是哪些?比如ASP.NET MVC、比如ASP.NET Web APi、比如EntityFramework,再比如数据库等等。如果面试者没有特别擅长的技术那我就简历上提出所熟悉和项目当中用到的技术进行提问。这里暂且不提其他技术,单单说EntityFramework,面试的面试者大部分都有用过EntityFramework,我就简单问了下,比如您用的EntityFramework版本是多少?答案是不知道,这个我理解,可能没去关心过这个问题,再比如我问您知道EntityFramework中有哪些继承策略,然后面试者要么是一脸懵逼,要么是不知道,要么回了句我们不用。这个我也能理解,重点来了,我问您在EntityFramwork中对于批量添加操作是怎么做的,无一例外遍历循环一个一个添加到上下文中去,结果令我惊呆了,或许是只关注于实现,很多开发者只关注这个能实现就好了,这里不过多探讨这个问题,每个人观点不一样。

  大部分人用EntityFramework时出现了问题,就吐槽EntityFramework啥玩意啊,啥ORM框架啊,各种问题,我只能说您根本不会用EntityFramework,甚至还有些人并发测试EntityFramework的性能,是的,没错,EntityFramework性能不咋的(这里我们只讨论EF 6.x),或者说在您实际项目当中有了点并发发现EF出了问题,又开始抱怨EF不行了,同时对于轻量级、跨平台、可扩展的EF Core性能秒杀EF,即使你并发测试EF Core性能也就那么回事,我想说的是你并发测试EF根本没有任何意义,请好生理解EF作为ORM框架出现的意义是什么,不就是为了让我们关注业务么,梳理好业务对象,在EF中用上下文操作对象就像直接操作表一样。然后我们回到EF抵抗并发的问题,有的童鞋认为EF中给我提供了并发Token和行版本以及还有事务,这不就是为了并发么,童鞋对于并发Token和行版本这是对于少量的请求可能存在的并发EF团队提出的基本解决方案,对于事务无论是同一上文抑或是跨上下文也好只是为了保证数据一致性罢了。要是大一点的并发来了,您难道还让EF不顾一切冲上去么,这无疑是飞蛾扑火自取灭亡,你到底会不会用EntityFramework啊。EF作为概念上的数据访问层应该是处于最底层,如果我们项目可预见没有所谓的并发问题,将上下文直接置于最上层比如控制器中并没有什么问题,但是项目比较大,随着用户量的增加,我们肯定是可预知的,这个我们需要从项目架构层面去考虑,此时在上下文上游必定还有其他比如C#中的并发队列或者Redis来进行拦截使其串行进行。

  有些人号称是对EntityFramwork非常了解,认为不就是增、删、该、查么,但是有的时候用出了问题就开始自我开解,我这么用没有任何问题啊,我们都知道在EF 6.x中确实有很多坑,这个时候就借这个缘由洗白了,这不是我的锅,结果EF背上了无名之锅,妄名之冤。是的,您们没有说错,EF 6.x是有很多坑,您避开这些坑不就得了,我只能说这些人太浮于表面不了解基本原理就妄下结论,你到底会不会用EntityFramework啊。好了来,免说我纸上谈兵,我来举两个具体例子,您们看你到底会不会用。

EntityFramework 6.x查询

static void Main(string[] args)

        {

            using (var ctx = new EfDbContext())

            {

                ctx.Database.Log = Console.WriteLine;


                var code = "Jeffcky";

                var order = ctx.Orders.FirstOrDefault(d => d.Code == code);           

            };

            Console.ReadKey();

        }

这样的例子用过EF 6.x的童鞋估计用烂了吧,然后查询出来的结果让我们也非常满意至少是达到了我们的预期,我们来看看生成的SQL语句。

 640?wx_fmt=png

请问用EF的您们发现什么没有,在WHERE查询条件加上了一堆没有用的东西,我只是查询Code等于Jeffcky的实体数据,从生成的SQL来看可查询Code等于Jeffcky的也可查询Code等于空的数据,要是我们如下查询,生成如上SQL语句我觉得才是我们所预期的对不对。

using (var ctx = new EfDbContext())

            {

                ctx.Database.Log = Console.WriteLine;


                var code = "Jeffcky";

                var orders = ctx.Orders.Where(d => d.Code == null || d.Code == code).ToList();


            };

如果您真的会那么一点点用EntityFramework,那么请至少了解背后生成的SQL语句吧,这是其中之一,那要是我们直接使用值查询呢,您们觉得是否和利用参数生成的SQL语句是一样的呢?

using (var ctx = new EfDbContext())

            {

                ctx.Database.Log = Console.WriteLine;


                var order = ctx.Orders.FirstOrDefault(d => d.Code == "Jeffcky");


            };

640?wx_fmt=png

出乎意料吧,利用值查询在WHERE条件上没有过多的条件过滤,而利用参数查询则是生成过多的条件筛选,到这里是不是就到此为止了呢,如果您们对于参数查询不想生成对空值的过滤,我们在上下文构造函数中可关闭这种所谓【语义可空】判断,如下:

public class EfDbContext : DbContext

    {

        public EfDbContext() : base("name=ConnectionString")

        {

            Configuration.UseDatabaseNullSemantics = true;

        }

     }

640?wx_fmt=png

// 摘要:
// 获取或设置一个值,该值指示当比较两个操作数,而它们都可能为 null 时,是否展示数据库 null 语义。默认值为 false。例如:如果 UseDatabaseNullSemantics
// 为 true,则 (operand1 == operand2) 将转换为 (operand1 = operand2);如果 UseDatabaseNullSemantics
// 为 false,则将转换为 (((operand1 = operand2) AND (NOT (operand1 IS NULL OR operand2
// IS NULL))) OR ((operand1 IS NULL) AND (operand2 IS NULL)))。
//
// 返回结果:
// 如果启用数据库 null 比较行为,则为 true;否则为 false。

在EF 6.x中对于查询默认情况下会进行【语义可空】筛选,通过如上分析,不知您们是否知道如上的配置呢。

EntityFramework 6.x更新

EF 6.x更新操作又是用熟透了吧,在EF中没有Update方法,而在EF Core中存在Update和UpdateRange方法,您们是否觉得更新又是如此之简单呢?我们下面来首先看一个例子,看看您们是否真的会用。

static Customer GetCustomer()

        {

            var customer = new Customer()

            {

                Id = 2,

                CreatedTime = DateTime.Now,

                ModifiedTime = DateTime.Now,

                Email = "2752154844@qq.com",

                Name = "Jeffcky1"

            };

            return customer;

        }

如上实体如我们请求传到后台需要修改的实体(假设该实体在数据库中存在哈),这里我们进行写死模拟。接下来我们来进行如下查询,您们思考一下是否能正常更新呢?

using (var ctx = new EfDbContext())

            {

                var customer = GetCustomer();

                var dataBaseCustomer = ctx.Customers.FirstOrDefault(d => d.Id == customer.Id);

                if (dataBaseCustomer != null)

                {

                    ctx.Customers.Attach(customer);

                    ctx.Entry(customer).State = EntityState.Modified;

                    if (ctx.SaveChanges() > 0)

                    {

                        Console.WriteLine("更新成功");

                    }

                    else

                    {

                        Console.WriteLine("更新失败");

                    }

                }


            };

首先我们根据传过来的实体主键去数据库中查询是否存在,若存在则将传过来的实体附加到上下文中(因为此时请求过来的实体还未被跟踪),然后将其状态修改为已被修改,最后提交,解释的是不是非常合情合理且合法,那是不是就打印更新成功了呢?

640?wx_fmt=png

看到上述错误想必有部分童鞋一下子就明白问题出在哪里,当我们根据传过来的实体主键去数据库查询,此时在数据库中存在就已被上下文所跟踪,然后我们又去附加已传过来的实体且修改状态,当然会出错因为在上下文已存在相同的对象,此时必然会产生已存在主键冲突。有的童鞋想了直接将传过来的实体状态修改为已修改不就得了么,如下:

using (var ctx = new EfDbContext())

            {

                var customer = GetCustomer();

                ctx.Entry(customer).State = EntityState.Modified;

                if (ctx.SaveChanges() > 0)

                {

                    Console.WriteLine("更新成功");

                }

                else

                {

                    Console.WriteLine("更新失败");

                }

            };

如此肯定能更新成功了,我想都不会这么干吧,要是客户端进行传过来的主键在数据库中不存在呢(至少我们得保证数据是已存在才修改),此时进行如上操作将抛出如下异常。

640?wx_fmt=png

此时为了解决这样的问题最简单的方法之一则是在查询实体是否存在时直接通过AsNoTracking方法使其不能被上下文所跟踪,这样就不会出现主键冲突的问题。

 var dataBaseCustomer = ctx.Customers.AsNoTracking().FirstOrDefault(d => d.Id == customer.Id);

640?wx_fmt=png

我们继续往下探讨 ,此时我们将数据库Email修改为可空(映射也要对应为可空,否则抛出验证不通过的异常,你懂的),如下图:

 640?wx_fmt=png

然后将前台传过来的实体进行如下修改,不修改Email,我们注释掉。

static Customer GetCustomer()

        {

            var customer = new Customer()

            {

                Id = 2,

                CreatedTime = DateTime.Now,

                ModifiedTime = DateTime.Now,

                //Email = "2752154844@qq.com",

                Name = "Jeffcky1"

            };

            return customer;

        }

我们接着再来进行如下查询试试看。

using (var ctx = new EfDbContext())

            {

                var customer = GetCustomer();

                var dataBaseCustomer = ctx.Customers

                    .AsNoTracking()

                    .FirstOrDefault(d => d.Id == customer.Id);

                if (dataBaseCustomer != null)

                {

                    ctx.Customers.Attach(customer);

                    ctx.Entry(customer).State = EntityState.Modified;

                    if (ctx.SaveChanges() > 0)

                    {

                        Console.WriteLine("更新成功");

                    }

                    else

                    {

                        Console.WriteLine("更新失败");

                    }

                }


            };

按 Ctrl+C 复制代码

640?wx_fmt=png

此时Email为可空,因为我们设置实体状态为Modified,此时将对实体进行全盘更新,所以对于设置实体状态为Modified是针对所有列更新,要是我们只想更新指定列,那这个就不好使了,此时我们可通过Entry().Property()...来手动更新指定列,比如如下:

using (var ctx = new EfDbContext())

            {

                var customer = GetCustomer();

                var dataBaseCustomer = ctx.Customers

                    .AsNoTracking()

                    .FirstOrDefault(d => d.Id == customer.Id);

                if (dataBaseCustomer != null)

                {

                    ctx.Customers.Attach(customer);

                    ctx.Entry(customer).Property(p => p.Name).IsModified = true;

                    ctx.Entry(customer).Property(p => p.Email).IsModified = true;

                    if (ctx.SaveChanges() > 0)

                    {

                        Console.WriteLine("更新成功");

                    }

                    else

                    {

                        Console.WriteLine("更新失败");

                    }

                }


            };


我们继续往下走。除了上述利用AsNoTracking方法外使其查询出来的实体未被上下文跟踪而成功更新,我们还可以使用手动赋值的方式更新数据,如下:

using (var ctx = new EfDbContext())

            {

                var customer = GetCustomer();

                var dataBaseCustomer = ctx.Customers

                    .FirstOrDefault(d => d.Id == customer.Id);

                if (dataBaseCustomer != null)

                {

                    dataBaseCustomer.CreatedTime = customer.CreatedTime;

                    dataBaseCustomer.ModifiedTime = customer.ModifiedTime;

                    dataBaseCustomer.Email = customer.Email;

                    dataBaseCustomer.Name = customer.Name;

                    if (ctx.SaveChanges() > 0)

                    {

                        Console.WriteLine("更新成功");

                    }

                    else

                    {

                        Console.WriteLine("更新失败");

                    }

                }


            };

如上也能更新成功而不用将查询出来的实体未跟踪,然后将前台传过来的实体进行附加以及修改状态,下面我们删除数据库中创建时间和修改时间列,此时我们保持数据库中数据和从前台传过来的数据一模一样,如下:

static Customer GetCustomer()

        {

            var customer = new Customer()

            {

                Id = 2,

                Email = "2752154844@qq.com",

                Name = "Jeffcky1"

            };

            return customer;

        }

640?wx_fmt=png

接下来我们再来进行如下赋值修改,你会发现此时更新失败的:

using (var ctx = new EfDbContext())

            {

                var customer = GetCustomer();

                var dataBaseCustomer = ctx.Customers

                    .FirstOrDefault(d => d.Id == customer.Id);

                if (dataBaseCustomer != null)

                {

                    dataBaseCustomer.Email = customer.Email;

                    dataBaseCustomer.Name = customer.Name;

                    if (ctx.SaveChanges() > 0)

                    {

                        Console.WriteLine("更新成功");

                    }

                    else

                    {

                        Console.WriteLine("更新失败");

                    }

                }


            };

640?wx_fmt=png

这是为何呢?因为数据库数据和前台传过来的数据一模一样,但是不会进行更新,毫无疑问EF这样处理是明智且正确的,无需多此一举更新,那我们怎么知道是否有不一样的数据进行更新操作呢,换句话说EF怎样知道数据未发生改变就不更新呢?我们可以用上下文属性中的ChangeTacker中的HasChanges方法,如果上下文知道数据未发生改变,那么直接返回成功,如下:

using (var ctx = new EfDbContext())

            {

                var customer = GetCustomer();

                var dataBaseCustomer = ctx.Customers

                    .FirstOrDefault(d => d.Id == customer.Id);

                if (dataBaseCustomer != null)

                {

                    dataBaseCustomer.Email = customer.Email;

                    dataBaseCustomer.Name = customer.Name;

                    if (!ctx.ChangeTracker.HasChanges())

                    {

                        Console.WriteLine("更新成功");

                        return;

                    }

                    if (ctx.SaveChanges() > 0)

                    {

                        Console.WriteLine("更新成功");

                    }

                    else

                    {

                        Console.WriteLine("更新失败");

                    }

                }


            };

好了到此为止我们已经看到关于更新已经有了三种方式,别着急还有最后一种,通过Entry().CurrentValues.SetValues()方式,这种方式也是指定更新,将当前实体的值设置数据库中查询出来所被跟踪的实体的值。如下:

using (var ctx = new EfDbContext())

            {

                var customer = GetCustomer();

                var dataBaseCustomer = ctx.Customers

                    .FirstOrDefault(d => d.Id == customer.Id);

                if (dataBaseCustomer != null)

                {

                    ctx.Entry(dataBaseCustomer).CurrentValues.SetValues(customer);

                    if (ctx.SaveChanges() > 0)

                    {

                        Console.WriteLine("更新成功");

                    }

                    else

                    {

                        Console.WriteLine("更新失败");

                    }

                }


            };

关于EF更新方式讲了四种,其中有关细枝末节就没有再细说可自行私下测试,不知道用过EF的您们是否四种都知道以及每一种对应的场景是怎样的呢?对于数据更新我一般直接通过查询进行赋值的形式,当然我们也可以用AutoMapper,然后通过HasChanges方法来进行判断。

EntityFramework 6.x批量添加

对于批量添加已经是EF 6.x中老掉牙的话题,但是依然有很多面试者不知道,我这里再重新讲解一次,对于那些私下不学习,不与时俱进的童鞋好歹也看看前辈们(不包括我)总经的经验吧,不知道为何这样做,至少回答答案是对的吧。看到下面的批量添加数据代码是不是有点想打人。

using (var ctx = new EfDbContext())

            {

                for (var i = 0; i <= 100000; i++)

                {

                    var customer = new Customer

                    {

                        Email = "2752154844@qq.com",

                        Name = i.ToString()

                    };

                    ctx.Customers.Add(customer);

                    ctx.SaveChanges();

                }

            };

至于原因无需我过多解释,如果您这样操作,那您这一天的工作大概也就是等着数据添加完毕,等啊等。再不济您也将SaveChanges放在最外层一次性提交啊,这里我就不再测试,浪费时间在这上面没必要,只要您稍微懂点EF原理至少会如下这么使用。

var customers = new List<Customer>();

            using (var ctx = new EfDbContext())

            {

                for (var i = 0; i <= 100000; i++)

                {

                    var customer = new Customer

                    {

                        Email = "2752154844@qq.com",

                        Name = i.ToString()

                    };

                    customers.Add(customer);

                }

                ctx.Customers.AddRange(customers);

                ctx.SaveChanges();

            };

如果您给我的答案如上,我还是认可的,要是第一种真的说不过去了啊。经过如上操作依然有问题,我们将所有记录添加到同一上下文实例,这意味着EF会跟踪这十万条记录, 对于刚开始添加的几个记录,会运行得很快,但是当越到后面到达到十万时,EF正在追踪更大的对象图,您们觉得恐怖不,这就是您不懂EF原理的代价,还对其进行诟病,吐槽性能可以,至少保证你写的代码没问题吧,我们进一步优化需要关闭自调用的DetectChanges方法无需进行对每一个添加的实体进行扫描。

 

var customers = new List<Customer>();

            using (var ctx = new EfDbContext())

            {

                bool acd = ctx.Configuration.AutoDetectChangesEnabled;

                try

                {

                    for (var i = 0; i <= 100000; i++)

                    {

                        var customer = new Customer

                        {

                            Email = "2752154844@qq.com",

                            Name = i.ToString()

                        };

                        customers.Add(customer);

                    }

                    ctx.Customers.AddRange(customers);

                    ctx.SaveChanges();

                }

                finally

                {

                    ctx.Configuration.AutoDetectChangesEnabled = acd;

                }

            };

此时我们通过局部关闭自调用DetectChanges方法,此时EF不会跟踪实体,这样将不会造成全盘扫描而使得我们不会处于漫长的等待,如此优化将节省大量时间。如果在我们了解原理的前提下知道添加数据到EF上下文中,随着数据添加到集合中也会对已添加的数据进行全盘扫描,那我们何不创建不同的上下文进行批量添加呢?未经测试在这种情况下是否比关闭自调用DetectChanges方法效率更高,仅供参考,代码如下:

 

public static class EFContextExtensions

    {

        public static EfDbContext BatchInsert<T>(this EfDbContext context, T entity, int count, int batchSize) where T : class

        {

            context.Set<T>().Add(entity);


            if (count % batchSize == 0)

            {

                context.SaveChanges();

                context.Dispose();

                context = new EfDbContext();

            }

            return context;

        }

    }

static void Main(string[] args)

        {

            var customers = new List<Customer>();

            EfDbContext ctx;

            using (ctx = new EfDbContext())

            {

                for (var i = 0; i <= 100000; i++)

                {

                    var customer = new Customer

                    {

                        Email = "2752154844@qq.com",

                        Name = i.ToString()

                    };

                    ctx = ctx.BatchInsert(customer, i, 100);

                }

                ctx.SaveChanges();

            };

            Console.ReadKey();

        }

总结

不喜勿喷,敢问您们到底会不会用EntityFramework啊,EF 6.x性能令人诟病但是至少得保证您们写的代码没问题吧,您们可结合Dapper使用啊,担心EF 6.x性能不行,那请用EntityFramework Core吧,你值得拥有。谨以此篇批判那些不会用EF的同行,还将EF和并发扯到一块,EF不是用来抵抗并发,它的出现是为了让我将重心放在梳理业务对象,关注业务上,有关我对EF 6.x和EF Core 2.0理解全部集成到我写的书《你必须掌握的EntityFramework 6.x与Core 2.0》最近即将出版,想了解的同行可关注下,谢谢。

原文地址: https://www.cnblogs.com/CreateMyself/p/8989983.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321385.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统复习笔记 04 Process 进程

[]进程的概念1.进程是操作系统执行的各种程序。2.现在的操作系统多为并发执行&#xff0c;具有许多新的特征。引入并发执行的目的是提高资源利用率。3.OS的基本特征是[并发与共享]。4.顺序环境计算机系统只有一个程序在执行&#xff0c;该程序独占系统的所有资源&#xff0c;其…

【动态规划】 多米诺骨牌 (ssl 1632/luogu 1282)

多米诺骨牌多米诺骨牌多米诺骨牌 Description Input 输入文件的第一行是一个正整数n(1≤n≤1000)&#xff0c;表示多米诺骨牌数。接下来的n行表示n个多米诺骨牌的点数。每行有两个用空格隔开的正整数&#xff0c;表示多米诺骨牌上下方块中的点数a和b&#xff0c;且1≤a&#…

为什么 web 开发人员需要迁移到. NET Core, 并使用 ASP.NET Core MVC 构建 web 和 API

2018 .NET开发者调查报告: .NET Core 是怎么样的状态&#xff0c;这里我们看到了还有非常多的.net开发人员还在观望&#xff0c;本文给大家一个建议。这仅代表我的个人意见, 我有充分的理由推荐.net 程序员使用. net core而不是. net Framework。有些人可能不同意我的观点, 但是…

CF1260C-Infinite Fence【结论题】

正题 题目链接:https://www.luogu.com.cn/problem/CF1260C 题目大意 无数个栏杆&#xff0c;rrr的倍数染成红色&#xff0c;bbb的倍数染成蓝色&#xff0c;是rrr和bbb的倍数的话可以选择一个染色&#xff0c;去掉没有染色的&#xff0c;是否有一种方案使得最长的染色快不超过…

【动态规划】 摆花 【NOIp普及组 2012 第三题】 (ssl 2360/luogu 1077)

摆花摆花摆花 题目大意 有n种花&#xff0c;每种花有ai支&#xff0c;取m支&#xff0c;有多少种取法&#xff1f;&#xff08;同一种花取第1&#xff0c;第3支和取第1&#xff0c;第2支算一种取法&#xff09; 解题方法&#xff1a; 用f[i][j]来表示前i种选j支的方案数&…

操作系统复习笔记 05 Thread 线程

进程的两个基本属性1.拥有资源的独立单位2.可独立调度和分派的基本单位进程的数目不宜过多&#xff0c;进程切换频率不宜过高&#xff0c;限制了并发程度。操作系统的设计目标是&#xff1a;提高并发度、减小系统开销。引入线程的目的是简化线程间的通信&#xff0c;以小的开销…

使用SonarCloud对.NET Core项目进行静态代码分析

本文将介绍如何使用SonarCloud进行.NET Core项目的静态代码分析。SonarCloud是SonarQube提供的基于云的版本&#xff0c;特别针对于开源项目是免费的。首先&#xff0c;在sonarcloud.io创建一个账号&#xff0c;你可以使用Github/BitBucket/Microsoft Live账户进行注册&#xf…

P6477-[NOI Online #2 提高组]子序列问题【线段树】

正题 题目链接:https://www.luogu.com.cn/problem/P6477 话说这是luogu的冥间数据 题目大意 nnn个数的序列&#xff0c;f(l,r)f(l,r)f(l,r)表示l∼rl\sim rl∼r有多少个不同的数字。 求∑l1n∑rln(f(l,r))2\sum_{l1}^n\sum_{rl}^n(f(l,r))^2l1∑n​rl∑n​(f(l,r))2 解题思路…

操作系统复习笔记 06 CPU Scheduling CPU调度

CPU的三级调度&#xff1a;1.高级调度(Long-term)&#xff1a;作业调度&#xff0c;从外存进内存2.低级调度(Short-term)&#xff1a;进程调度&#xff0c;分配处理机3.中级调度(Medium-term)&#xff1a;对换通过多道程序设计得到CPU的最高使用率。CPU-IO脉冲周期&#xff1a;…

【动态规划】 石子合并问题(环形) (ssl 1597)

石子合并问题石子合并问题石子合并问题 Description 在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2 堆石子合并成新的一堆&#xff0c;并将新的一堆石子数记为该次合并的得分。试设计一个算法&#xff0c;计算出将n堆石子合并成…

P6102-[EER2]谔运算【位运算】

正题 题目链接:https://www.luogu.com.cn/problem/P6102?contestId26472 题目大意 nnn个数的序列aaa&#xff0c;求 ∑i1n∑j1n∑k1n∑l1n(aioraj)xor(akandal)\sum_{i1}^n\sum_{j1}^n\sum_{k1}^n\sum_{l1}^n(a_i\ or\ a_j)\ xor\ (a_k\ and\ a_l)i1∑n​j1∑n​k1∑n​l1∑n…

操作系统复习笔记 07 Process Synchronization 进程同步

背景&#xff1a;1.对共享数据的并发访问可能导致数据的不一致性。2.要保持数据的一致性&#xff0c;就需要一种保证并发进程正确执行顺序机制。3.解决有界缓冲区问题的共享内存方法在count上存在竞争条件。4.进程间的制约关系&#xff1a;——间接制约&#xff1a;有些资源需要…

【动态规划】拔河比赛 (ssl 1638)

拔河比赛拔河比赛拔河比赛 Description 一个学校举行拔河比赛&#xff0c;所有的人被分成了两组&#xff0c;每个人必须&#xff08;且只能够&#xff09;在其中的一组&#xff0c;要求两个组的人数相差不能超过1&#xff0c;且两个组内的所有人体重加起来尽可能地接近。 In…

特长生考试相关

水一手游记 一大早起来像个那啥一样在校训石前等&#xff08;旁边一群看猴子一样&#xff09; 然后车上点个人就去公费旅游&#xff08;半个小时车程&#xff0c;甚至没有饭吃&#xff09; 然后到那边量完体温见了一下熟人就开始了 T1高精度&#xff0c;历年最难T1还要判负数然…

Build 2018,给你带来全新的开发者体验, .NET Core 3.0带来桌面支持

Build 2018 主旨演讲的主题是 Azure 云和 AI、物联网、AR等技术&#xff0c;以及开发者相关内容的宣布。在今天的Build大会上&#xff0c;微软宣布目前已有超过7亿台设备运行Windows 10系统。去年这个数字为5亿。Office 365目前每个月有1.35亿活跃的商业用户&#xff0c;去年为…

【动态规划】大厅安排 (ssl 1212)

大厅安排大厅安排大厅安排 Description 有一个演讲大厅需要GEORGE管理&#xff0c;演讲者们事先定好了需要演讲的起始时间和中止时间。GEORGE想让演讲大厅得到最大可能的使用。我们要接受一些预定而拒绝其他的预定&#xff0c;目标自然是使演讲者使用大厅的时间最长。为方便起…

《你必须掌握的Entity Framework 6.x与Core 2.0》书籍出版

前言到目前为止写过刚好两百来篇博客&#xff0c;看过我博客的读者应该大概知道我每一篇博客都沿袭着一贯的套路&#xff0c;从前言到话题最终到总结&#xff0c;本文依然是一如既往的套路&#xff0c;但是不是介绍技术&#xff0c;也可说是介绍技术&#xff0c;不过是介绍书中…

Loj#2035-[SDOI2016]征途【斜率优化】

正题 题目链接:https://loj.ac/problem/2035 题目大意 nnn个数字分成mmm段&#xff0c;要求方差最小。 解题思路 首先方差的公式∑i1n(xi−∣x∣)2\sum_{i1}^n(x_i-|x|)^2i1∑n​(xi​−∣x∣)2 其中∣x∣|x|∣x∣是不变的&#xff0c;定义w∣x∣w|x|w∣x∣ 设fi,jf_{i,j}fi,…

可持久化线段树小结

学了可持久化线段树有一段时间了&#xff0c;一直没拿出时间来整理一下&#xff0c;刚好今天有空&#xff0c;就写一写。 可持久化的含义是对于每次修改操作都将产生一个新版本的线段树&#xff0c;并且旧版本的线段树仍然保留可以随时访问。 基于这个目的&#xff0c;我们可…

【动态规划】 数字游戏 (ssl 1653)

数字游戏 题目大意&#xff1a; 有n个数&#xff0c;分别为a[1] (序号为1),a[2] (序号为2),a[3]…a[n]&#xff0c;让你选m个数&#xff0c;每选一个数&#xff0c;就要减去已选个数(不算当前数)*b[i] (i为当前值的序号)&#xff0c;所选数的最大值(要减去相应的b) 原题 小…