پردازشهای Async در Entity framework 6
نویسنده: وحید نصیری
تاریخ: ۱۳۹۳/۰۳/۲۹ ۰:۲۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
QueryableExtensions: AllAsync AnyAsync AverageAsync ContainsAsync CountAsync FirstAsync FirstOrDefaultAsync ForEachAsync LoadAsync LongCountAsync MaxAsync MinAsync SingleAsync SingleOrDefaultAsync SumAsync ToArrayAsync ToDictionaryAsync ToListAsync DbSet: FindAsync DbContext: SaveChangesAsync Database: ExecuteSqlCommandAsync
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<BlogPost> BlogPosts { get; set; }
}
public class BlogPost
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
public int UserId { get; set; }
} public class MyContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<BlogPost> BlogPosts { get; set; }
public MyContext()
: base("Connection1")
{
this.Database.Log = sql => Console.Write(sql);
}
} private async Task<User> addUserAsync(CancellationToken cancellationToken = default(CancellationToken))
{
using (var context = new MyContext())
{
var user = context.Users.Add(new User
{
Name = "Vahid"
});
context.BlogPosts.Add(new BlogPost
{
Content = "Test",
Title = "Test",
User = user
});
await context.SaveChangesAsync(cancellationToken);
return user;
}
} [AsyncTimeout(8000)] public async Task<ActionResult> Index(CancellationToken cancellationToken)
var user = await addUserAsync();
Console.WriteLine("user id: {0}", user.Id);
private async Task<User> updateAsync(CancellationToken cancellationToken = default(CancellationToken))
{
using (var context = new MyContext())
{
var user1 = await context.Users.FindAsync(cancellationToken, 1);
if (user1 != null)
user1.Name = "Vahid N.";
await context.SaveChangesAsync(cancellationToken);
return user1;
}
}
private async Task<int> deleteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
using (var context = new MyContext())
{
var user1 = await context.Users.FindAsync(cancellationToken, 1);
if (user1 != null)
context.Users.Remove(user1);
return await context.SaveChangesAsync(cancellationToken);
}
} public async Task<List<TEntity>> GetAllAsync()
{
return await Task.Run(() => _tEntities.ToList());
} private async Task<List<User>> getUsersAsync(CancellationToken cancellationToken = default(CancellationToken))
{
using (var context = new MyContext())
{
return await context.Users.ToListAsync(cancellationToken);
}
} internal override async Task<long> ExecuteAsync( //... rowsAffected = await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); //...
var connectionString = "........";
var sql = @"......"";
var users = new List<User>();
using (var cnx = new SqlConnection(connectionString))
{
using (var cmd = new SqlCommand(sql, cnx))
{
await cnx.OpenAsync();
using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection))
{
while (await reader.ReadAsync())
{
var user = new User
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
};
users.Add(user);
}
}
}
} // multiple operations
private static async Task loadAllAsync(CancellationToken cancellationToken = default(CancellationToken))
{
using (var context = new MyContext())
{
var task1 = context.Users.ToListAsync(cancellationToken);
var task2 = context.BlogPosts.ToListAsync(cancellationToken);
await Task.WhenAll(task1, task2);
// use task1.Result
}
} An unhandled exception of type 'System.NotSupportedException' occurred in mscorlib.dll Additional information: A second operation started on this context before a previous asynchronous operation completed. Use 'await' to ensure that any asynchronous operations have completed before calling another method on this context. Any instance members are not guaranteed to be thread safe.
public class ProductRepository<T> where T : class
{
protected DbContext _context;
public ProductRepository(DataContext context)
{
_context = context;
}
// GetAll public async Task<List<T>> GetAllAsync()
{
return await _dbContext.Set<T>().ToListAsync();
} مثلا برای همچین کدی میشه از روش بالا استفاده کرد مشکل حل میشه ؟
{
for (int i = 1; i <=500; i++)
{
ThreadPool.QueueUserWorkItem(Execute, i + 1);
}
}
void Execute(Object obj)
{
int thread = (int)obj;
try
{
using (TestEntities ctx = new TestEntities())
{
int i = 1;
foreach (var v in ctx.Customers)
{
Thread.Sleep(i * 1000);
i++;
}
}
listBox1.Items.Add("Thread " + thread.ToString() + " End Success ");
}
catch (Exception e)
{
listBox1.Items.Add("Thread " + thread.ToString() + " Error :" + e.Message);
}
}
PM> update-package
using System.Data.Entity;
public async Task<IList<NewsSliderModel>> GetNewsSliderTable(CancellationToken cancellationToken = default(CancellationToken))
{
IQueryable<News> selectednews = _news.Take(_sliderTakeCount).AsQueryable();
...
...
return await selectednews.Select(x => new NewsSliderModel
{
NewsId = x.Id,
Title = x.Title,
ImagePath = x.ImagePath,
ImageTitle = x.ImageTitle,
ImageDescription = x.ImageDescription,
}).ToListAsync();
} public virtual async Task<ActionResult> MainSlider()
{
IList<NewsSliderModel> SliderList = await _newsService.GetNewsSliderTable(Order.Descending, NewsOrderBy.Id);
return PartialView(MVC.Home.Views._MainSlider, SliderList.ToList());
} HttpServerUtility.Execute blocked while waiting for an asynchronous operation to complete.
@Html.Action(MVC.Home.ActionNames.MainSlider, MVC.Home.Name)
... at System.Data.Entity.Infrastructure.IDbAsyncEnumerableExtensions.<FirstOrDefaultAsync>d__25`1.MoveNext() --- End of stack trace from previous location where exception was thrown --- ... at MyApplication.ServiceLayer.EfServices.Content.BlogService.<GetBlogByIdForPublicViewAsync>d__24.MoveNext() --- End of stack trace from previous location where exception was thrown --- ... at MyApplication.Controllers.BlogController.<Details>d__87.MoveNext() --- End of stack trace from previous location where exception was thrown ---
public async Task<BlogViewModel> GetBlogByIdForPublicViewAsync(int blogId)
{
var result = await _blogs
.ProjectTo<BlogViewModel>()
.FirstOrDefaultAsync(a => a.Id == blogId);
return result;
}
public virtual async Task<ActionResult> Details(int id)
{
var blog = await _blogService.GetBlogByIdForPublicViewAsync(id);
return View("Details", blog);
} public BlogViewModel GetBlogByIdForPublicView(int blogId)
{
var result = _blogs
.ProjectTo<BlogViewModel>()
.First(a => a.Id == blogId);
result.Item1 = ... get some item from db;
result.Item2 = ... get another item from db;
return result;
} [HttpPost]
[AjaxOnly]
public virtual async Task<ActionResult> GetParts([DataSourceRequest] DataSourceRequest request)
{
return await DoBaseOperationAsync(() =>
{
var result = _partService.GetParts.Where(p => p.IsActive).AsLookupItemModel(p => p.PartId, p => p.CodeName);
var data = result.ToDataSourceResult(request);
return Json(data);
});
} protected async Task<ActionResult> DoBaseOperationAsync(Func<ActionResult> func, string title = null, string message = null, MessageType messageType = MessageType.Error)
{
try
{
AsyncManager.OutstandingOperations.Increment();
var cultureInfo = new CultureInfo(CultureHelper.GetCultureString());
return func != null ? await Task.Factory.StartNew(() =>
{
System.Web.HttpContext.Current = ControllerContext.HttpContext.ApplicationInstance.Context;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureInfo.Name);
return func.Invoke();
}) : null;
}
catch (Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
// Some code for error handling
}
} طبق گفته شما، چون استفاده از اعمال async، ترد جدیدی ایجاد نمی کند، چه زمان باید از thread ها و چه زمانی بهتر است از اعمال async استفاده کنیم؟ آیا با توجه به سربار کمتر async بهتر نیست همیشه به عنوان جایگزینی برای thread ها از اون ها استفاده کرد؟ و مسئله دوم اینکه متدهایی مانند Task.Run که تقلبی هستند، برای چه منظوری ارائه شده اند؟
مطالب دوره «مبانی Async در C# 5» را مطالعه کنید. با مفاهیمی مانند IO bound opertaions و CPU bound operations، مقیاسپذیری برنامههای وب، خالی کردن تردجاری، کار با برنامههای غیر وبی و امثال آن آشنا خواهید شد.