EF Data Operation With Async Task

本文展示了一个使用Entity Framework进行异步数据操作的例子,包括添加数据及查询操作,并附带完整的代码实现。

EF的性能问题一直受人诟病,其实EF通过异步操作在一定程度了缓解了性能问题,同时EF支持二级缓存,这两种方式都为提高EF的性能提供了帮助。今天写了一个异步的例子,代码如下,仅供参考!

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Net.Mime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace EFAsync
{
    class Program
    {
        static void Main(string[] args)
        {
            var task = AsycOperation();
            task.Wait();
            Console.ReadKey();
        }

        private static async Task AsycOperation()
        {
            using (var ctx = new ApplicationDbContext())
            {
                Console.WriteLine("准备添加数据,当前线程Id为{0}", 
                    Thread.CurrentThread.ManagedThreadId);
                ctx.Empoyees.Add(new Empoyee()
                {
                    EmpoyeeName = "justin",
                    Address = "shanghai",
                    Email = "justinfu@wicresoft.com"
                });

                await ctx.SaveChangesAsync();

                Console.WriteLine("数据保存完成,当前线程Id为{0}", 
                    Thread.CurrentThread.ManagedThreadId);

                Console.WriteLine("开始执行查询,当前线程Id为{0}", 
                    Thread.CurrentThread.ManagedThreadId);

                var employees = await (from employee 
                                           in ctx.Empoyees 
                                       select employee).ToListAsync();

                Console.WriteLine("遍历获得所有学生的姓名,当前线程Id为{0}", 
                    Thread.CurrentThread.ManagedThreadId);

                foreach (var e in employees)
                {
                    Console.WriteLine("学生姓名为:{0}", e.EmpoyeeName);
                }
            }
        }
    }
}


ApplicationDbContext

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EFAsync
{
    class ApplicationDbContext:DbContext
    {
        public ApplicationDbContext()
            :base("name=ModelsContainer")
        {
            
        }

        public DbSet<Empoyee> Empoyees { get; set; }
    }
}
Employee

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EFAsync
{
    class Empoyee
    {
        public int Id { set; get; }

        public string EmpoyeeName { set; get; }

        public string Address { set; get; }

        public string Email { set; get; }
    }
}
App.config

 <connectionStrings>
    <add name="ModelsContainer" 
         connectionString="Data Source=(local);Database=HibernateDB;User ID=sa; Password=1234;"
         providerName="System.Data.SqlClient"/>
 </connectionStrings>
效果:






public class FliggyInterpreter : Interpreter { #region 基础声明 //const int SleepTime = 800;//线程休眠时间 (毫秒) //HotelDbContext _context = new HotelDbContext(System.Configuration.ConfigurationManager.ConnectionStrings["HotelDbContext"].ConnectionString); // HotelOrderDbContext _context; private static readonly ThreadLocal<Random> _appRandom = new ThreadLocal<Random>(() => new Random()); OrderRepository _orderRepository; Account _account; AutoGrabblerManager _manager { get; set; } ILogger<FliggyInterpreter> _logger { get; set; } private readonly SqlHelp _connection; //public MyRepository _mySql; static string connectionString = "Data Source=group-hotel.mysql.polardb.rds.aliyuncs.com;Database=tcorder;User ID=huazhu_user;Password=HmMD5GuqF&&C;pooling=true;port=3306;sslmode=none;CharSet=utf8;"; static MySqlConnection connection; static string fliggyconnectionString = "Data Source=group-hotel.mysql.polardb.rds.aliyuncs.com;Database=fliggyorder;User ID=huazhu_user;Password=HmMD5GuqF&&C;pooling=true;port=3306;sslmode=none;CharSet=utf8;"; static MySqlConnection fliggyconnection; static string meituanconnectionString = "Data Source=group-hotel-2.mysql.polardb.rds.aliyuncs.com;Database=meituanorder;User ID=meituanorder;Password=X5qnhtGh1veK$i2x;pooling=true;port=3306;sslmode=none;CharSet=utf8;"; static MySqlConnection meituanconnection; static string ylconnectionString = "Data Source=ebooking-pub.rwlb.rds.aliyuncs.com;Database=yinglvorder;User ID=yinglvorder;Password=uLwf6@vyuXkWuaL;pooling=true;port=3306;sslmode=none;CharSet=utf8;"; static MySqlConnection ylconnection; public FliggyInterpreter(AutoGrabblerManager manager, OrderRepository orderRepository, SqlHelp connection/*, MyRepository mySql*/, ILogger<FliggyInterpreter> logger) { this._orderRepository = orderRepository; this._logger = logger; this._manager = manager; this._connection = connection; //this._mySql = mySql; CookieBox = new CookieContainer(); } public async Task NewFliggyHZFetchList(List<orders> orders, int type) { var _context = _orderRepository.GetContext(); try { var SelfHotels = await _context.HO_M_SelfHotel.AsNoTracking().Select(a => a.HotelId).ToListAsync(); int i = 0; //orders = orders.Where(a => a.TCCode == "4269736080805835619").ToList(); foreach (var item in orders) { //if (item.TCCode != "2391806715309212886") // continue; HotelOrderDetail detailData = new HotelOrderDetail(); NewADDFliggyJsonToModel(detailData, item, type); if (detailData.RoomID.Contains(","))//判断是否自签酒店 { var hid = detailData.RoomID.Split(',')[0]; if (SelfHotels.Contains(hid)) { detailData.Remark += "转自签"; } } if (detailData.BookTime < DateTime.Now.AddMonths(-10))//预定时间 久远的单子不进行处理 { continue; } if (detailData.UpdateTime > detailData.StayDateEnd.Value.AddMonths(1))//忽略 退房的,有又更新日期 { continue; } i++; try { var entity = _context.HO_O_HotelOrderDetails.Where(m => m.PlatOrderNo == item.TCCode).OrderByDescending(m => m.Id).FirstOrDefault(); var SettlePrice = detailData.AmountYingShou * 0.894M; detailData.AmountShiShou = detailData.AmountYingShou * 0.894M; if (entity == null || entity.Id == 0) { //HotelOrderDetail entity = _context.HO_O_HotelOrderDetails.LastOrDefault(m => m.FromID == detailData.FromID); //HotelOrderDetail entity = await _orderRepository.GetDetailByFromIDAsync(detailData.FromID); var flag = _context.HO_O_HotelOrderDetails.Where(m => m.PlatOrderNo == detailData.PlatOrderNo).OrderByDescending(m => m.Id).FirstOrDefault(); //数据库没有这条记录 if (flag == null) { //_manager.LogPolicy(detailData.PlatOrderNo, detailData.RoomID, detailData.BookTime.ToString("yyyy-MM-dd"));// 执行 sql ,记录实时的政策信息 //添加 await AddOrder(detailData, SettlePrice);//添加到数据库 } else { //如果有,但是他的FromID不为空 也添加 if (flag.FromID != null) { _manager.LogPolicy(detailData.PlatOrderNo, detailData.RoomID, detailData.BookTime.ToString("yyyy-MM-dd"));// 执行 sql ,记录实时的政策信息 //添加 await AddOrder(detailData, SettlePrice);//添加到数据库 } } //否则忽略 } else { //更新采购单关联 自动回填 #region 自动回填-接口 var order = _context.HO_O_HotelOrders.Where(m => m.PlatOrderNo == detailData.PlatOrderNo).FirstOrDefault(); //var WaiCaiNo = item.Value<string>("supCode"); var Purchase = _context.HO_O_HotelOrderPurchase.Where(a => a.PlatOrderNo == detailData.PlatOrderNo).FirstOrDefault(); //未处理的订单自动完成 不能是采购亿客行的 if (Purchase != null && order.StateAuditor < 1 && order.HandState < 2 && detailData.HotelID == 0) { string url = NewUrl + "/Hotel/HotelOrder/SetHandStateInterface"; var postDates = "{\"id\":" + order.Id + ",\"state\":2}"; JObject obj = HttpUtility.JsonPostObject(new Uri(url), postDates, CookieBox); url = NewUrl + "/Hotel/HotelOrder/SetAuditorInterface/" + order.Id; var State = HttpUtility.PostDate(new Uri(url), "", CookieBox, null); } #endregion if (detailData.UpdateTime > entity.UpdateTime || detailData.PlatOrderState != entity.PlatOrderState || detailData.PlatOrderType != entity.PlatOrderType || detailData.AmountYingShou != entity.AmountYingShou || order.AmountYingShou != detailData.AmountYingShou || detailData.AmountShiShou != entity.AmountShiShou || order.OrderState != detailData.OrderState || order.OrderType != detailData.OrderType /*|| detailData.AmountYingFu != entity.AmountYingFu || order.AmountYingFu != detailData.AmountYingFu*/ || detailData.HotelName != entity.HotelName || order.HotelName != detailData.HotelName || detailData.Room != entity.Room || order.Room != detailData.Room/* || detailData.Remark != entity.Remark || order.Remark != detailData.Remark*/) { await DetailUpdate(entity, detailData, false, SettlePrice); } } } catch (Exception ex) { } } } catch (Exception ex) { // 记录详细的错误信息 Console.WriteLine($"Error: {ex.Message}"); Console.WriteLine($"StackTrace: {ex.StackTrace}"); if (ex.InnerException != null) { Console.WriteLine($"InnerException: {ex.InnerException.Message}"); } } } } using B_HotelOrder.Context; using B_HotelOrder.Model; using B_HotelOrder.Model.Event; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Utility.EventBus; namespace B_HotelOrder.AutoGrabber.Refactored { public class OrderRepository { HotelOrderDbContext _context; IEventBus _eventBus; public OrderRepository(HotelOrderDbContext context, IEventBus eventBus) { _context = context; _eventBus = eventBus; } public async Task<HotelOrder> AddAsync(HotelOrder order) { if (order.Id > 0) { _context.Entry(order).State = EntityState.Modified; } else _context.Add(order); await _context.SaveChangesAsync(); if (_eventBus != null) { AddHotelOrderEvent _event = new AddHotelOrderEvent(); _event.OrderID = order.Id.ToString(); _eventBus.Publish(_event); } return order; } public async Task<HotelOrder> SendBusAsync(HotelOrder order) { if (_eventBus != null) { AddHotelOrderEvent _event = new AddHotelOrderEvent(); _event.OrderID = order.Id.ToString(); _eventBus.Publish(_event); } return order; } public async Task UpdateAsync(HotelOrder order) { _context.Entry(order).State = EntityState.Modified; await _context.SaveChangesAsync(); } public async Task<HotelOrder> GetAsync(int orderId) { throw new NotImplementedException(); } public async Task<HotelOrder> GetByPlatOrderNoAsync(string PlatOrderNo) { return await _context.HO_O_HotelOrders.FirstOrDefaultAsync(m => m.PlatOrderNo == PlatOrderNo); } public HotelOrderDbContext GetContext() { return _context; } public async Task<HotelOrderDetail> AddDetailAsync(HotelOrderDetail order) { _context.Add(order); await _context.SaveChangesAsync(); return order; } public async Task<HotelOrderDetail> GetDetailByPlatOrderNoAsync(string PlatOrderNo) { //return await _context.HO_O_HotelOrderDetails.LastOrDefaultAsync(m => m.PlatOrderNo == PlatOrderNo); return await _context.HO_O_HotelOrderDetails.Where(m => m.PlatOrderNo == PlatOrderNo).OrderByDescending(m => m.Id).FirstOrDefaultAsync(); } public async Task UpdateDetailAsync(HotelOrderDetail order) { _context.Entry(order).State = EntityState.Modified; await _context.SaveChangesAsync(); } /// <summary> /// 移除未收款的收款记录 /// </summary> /// <param name="HotelOrderDetailId"></param> /// <param name="PaymentType"></param> public async Task RemovePaymentInfo(int HotelOrderDetailId) { var payInfoList = await _context .HO_O_HotelPaymentInfos .Where(m => m.HotelOrderDetailId == HotelOrderDetailId && m.PaymentType == 0) .ToListAsync(); _context.RemoveRange(payInfoList); await _context.SaveChangesAsync(); } public async Task<HotelOrderDetail> GetDetailByFromIDAsync(string fromID) { //return await _context.HO_O_HotelOrderDetails.LastOrDefaultAsync(m => m.FromID == fromID); return await _context.HO_O_HotelOrderDetails.Where(m => m.FromID == fromID).OrderByDescending(m => m.Id).FirstOrDefaultAsync(); } public async Task<HotelOrderDetail> GetDetailByFromIDAndPlatOrderNoAsync(string fromID, string platOrderNo) { return await _context.HO_O_HotelOrderDetails.FirstOrDefaultAsync(m => m.FromID != fromID && m.PlatOrderNo == platOrderNo); } /// <summary> /// excludeOrderState /// </summary> /// <param name="fromID"></param> /// <param name="platOrderNo"></param> /// <param name="excludeOrderState">排除的订单状态</param> /// <returns></returns> public async Task<HotelOrderDetail> GetDetailByFromIDAndPlatOrderNoAsync(string fromID, string platOrderNo, int excludeOrderState) { return await _context. HO_O_HotelOrderDetails .FirstOrDefaultAsync(m => m.FromID != fromID && m.PlatOrderNo == platOrderNo && m.OrderState != excludeOrderState); } public async Task<List<HotelOrderDetail>> GetDetailByPlatOrderStateAndPOrderIDAsync(string platOrderNo, int pOrderID) { return await _context.HO_O_HotelOrderDetails.Where(m => m.PlatOrderState == platOrderNo && m.POrderID == pOrderID).ToListAsync(); } } } 查询语句报错: Error: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe. Error: A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: SSL Provider, error: 0 - 等待的操作过时。) StackTrace: at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection() at Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSectionAsync(CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Query.Internal.AsyncLinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext(CancellationToken cancellationToken) at System.Linq.AsyncEnumerable.Aggregate_[TSource,TAccumulate,TResult](IAsyncEnumerable`1 source, TAccumulate seed, Func`3 accumulator, Func`2 resultSelector, CancellationToken cancellationToken) at B_HotelOrder.AutoGrabber.Refactored.FliggyInterpreter.NewFliggyHZFetchList(List`1 orders, Int32 type) in D:\MeipiaoTiket_v2\MeipiaoTicketSystem\HotelOrder\B_HotelOrder.AutoGrabber.Refactored\FliggyInterpreter.cs:line 3098
01-01
An exception occurred in the database while iterating the results of a query for context type 'B_HotelOrder.Context.HotelOrderDbContext'. System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first. at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) at System.Data.SqlClient.SqlCommand.ValidateCommand(Boolean async, String method) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite, String method) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.ExecuteReader() at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues) at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded) at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found) at lambda_method(Closure ) at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ResultEnumerable`1.GetEnumerator() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results, QueryContext queryContext, IList`1 entityTrackingInfos, IList`1 entityAccessors)+MoveNext() at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found) at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_1`1.<CompileQueryCore>b__0(QueryContext qc) There is already an open DataReader associated with this Command which must be closed first.|contextType=B_HotelOrder.Context.HotelOrderDbContext, newline= , error=System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first. at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command) at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command) at System.Data.SqlClient.SqlCommand.ValidateCommand(Boolean async, String method) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite, String method) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehav
最新发布
01-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值