2016-11-04 3 views
1

쿼리를 수행하는 데 더 많은 Entity Framework 관련 테스트 방법을 테스트하기 위해 Github 프로젝트를 수정했습니다.Entity Framework 6 비동기 메서드 성능과 동기화 메서드

Link

모델 :

[Table("Player")] 
public partial class Player 
{ 
    public int Id { get; set; } 

    [Required] 
    [StringLength(200)] 
    public string FirstName { get; set; } 

    [Required] 
    [StringLength(200)] 
    public string LastName { get; set; } 

    public DateTime DateOfBirth { get; set; } 

    public int TeamId { get; set; } 

    public virtual Team Team { get; set; } 
} 

[Table("Team")] 
public partial class Team 
{ 
    public Team() 
    { 
     Players = new HashSet<Player>(); 
    } 

    public int Id { get; set; } 

    [Required] 
    [StringLength(200)] 
    public string Name { get; set; } 

    public DateTime FoundingDate { get; set; } 

    public int SportId { get; set; } 

    public virtual ICollection<Player> Players { get; set; } 

    public virtual Sport Sport { get; set; } 
} 

[Table("Sport")] 
public partial class Sport 
{ 
    public Sport() 
    { 
     Teams = new HashSet<Team>(); 
    } 

    public int Id { get; set; } 

    [StringLength(100)] 
    public string Name { get; set; } 

    public virtual ICollection<Team> Teams { get; set; } 
} 

내가 무엇을 테스트입니다 것은 이런 것들이다 :

EF "조정"- FirstOrDefault()와 ToList()

context.Players.FirstOrDefault(x => x.Id == id); 

context.Players.AsNoTracking().Where(x => x.TeamId == teamId).ToList(); 

context.Teams.AsNoTracking().Include(x => x.Players).Where(x => x.SportId == sportId).ToList(); 

EF "비동기"- DTO에 FirstOrDefaultAsync()와 선택과 ToListAsync()

await context.Players.FirstOrDefaultAsync(x => x.Id == id); 

await context.Players.AsNoTracking().Where(x => x.TeamId == teamId).ToListAsync(); 

await context.Teams.AsNoTracking().Include(x => x.Players).Where(x => x.SportId == sportId).ToListAsync(); 

EF "동기화"DTO에 선택과

context.Players.Select(p => new PlayerDTO() 
       { 
        Id = p.Id, 
        FirstName = p.FirstName, 
        DateOfBirth = p.DateOfBirth, 
        LastName = p.LastName, 
        TeamId = p.TeamId 

       }).FirstOrDefault(x => x.Id == id); 

context.Players.Where(x => x.TeamId == teamId).Select(p => new PlayerDTO() 
       { 
        Id = p.Id, 
        FirstName = p.FirstName, 
        DateOfBirth = p.DateOfBirth, 
        LastName = p.LastName, 
        TeamId = p.TeamId 
       }).ToList(); 

context.Teams.Where(x => x.SportId == sportId).Select(t => new TeamDTO() 
        { 
         Id = t.Id, 
         FoundingDate = t.FoundingDate, 
         Name = t.Name, 
         SportId = t.SportId, 
         Players = t.Players.Select(p => new PlayerDTO() 
         { 
          Id = p.Id, 
          FirstName = p.FirstName, 
          DateOfBirth = p.DateOfBirth, 
          LastName = p.LastName, 
          TeamId = p.TeamId 
         }).ToList() 
        }).ToList(); 

EF "비동기" 객체를 객체

await context.Players.Select(p => new PlayerDTO() 
       { 
        Id = p.Id, 
        FirstName = p.FirstName, 
        DateOfBirth = p.DateOfBirth, 
        LastName = p.LastName, 
        TeamId = p.TeamId 

       }).FirstOrDefaultAsync(x => x.Id == id); 

await context.Players.Where(x => x.TeamId == teamId).Select(p => new PlayerDTO() 
       { 
        Id = p.Id, 
        FirstName = p.FirstName, 
        DateOfBirth = p.DateOfBirth, 
        LastName = p.LastName, 
        TeamId = p.TeamId 
       }).ToListAsync(); 

await context.Teams.Where(x => x.SportId == sportId).Select(t => new TeamDTO() 
       { 
        Id = t.Id, 
        FoundingDate = t.FoundingDate, 
        Name = t.Name, 
        SportId = t.SportId, 
        Players = t.Players.Select(p => new PlayerDTO() 
        { 
         Id = p.Id, 
         FirstName = p.FirstName, 
         DateOfBirth = p.DateOfBirth, 
         LastName = p.LastName, 
         TeamId = p.TeamId 
        }).ToList() 
       }).ToListAsync(); 

제 결과는 상당히 귀찮습니다. 주로 MS가 EF의 비동기 부분을 홍보하기 때문에.

내 결과 : (밀리 초 단위) 스포츠의

수 : 8, 팀 수 : 30, 플레이어 수 : 100

EntityFrameworkAsyncDTO Results 
Run # Player by ID   Players per Team    Teams per Sport 
0    1,46     3,47     35,88 
1    1,04     3      33 
2    1,02     3,3      33,75 
3    1,03     3      31,75 
4    1,1      3,27     31,38 
EntityFrameworkAsync Results 
Run # Player by ID   Players per Team    Teams per Sport 
0    1,17     3,53     57 
1    1,01     3      48,62 
2    0,99     3,03     47,88 
3    1,02     3,07     51 
4    1      3,03     48,88 
EntityFrameworkDTO Results 
Run # Player by ID   Players per Team    Teams per Sport 
0    0,02     3      13,25 
1    0,01     2,8      13,12 
2    0,15     2,97     13,25 
3    0,02     2,9      13,25 
4    0,05     2,8      13,12 
EntityFramework Results 
Run # Player by ID   Players per Team    Teams per Sport 
0    0,01     2,27     28,38 
1    0,01     2,4      28,25 
2    0      2,13     28,5 
3    0,01     2,17     27,5 
4    0,01     2,13     29 
ADONET Results 
Run # Player by ID   Players per Team    Teams per Sport 
0    0      2,03     11,75 
1    0      2      12,62 
2    0      2      11,38 
3    0      2      12,38 
4    0      2      11,25 
내가 추가 한

/편집하여 ADO.NET 시간 결과 목록을 참조로 사용합니다.

제 질문은 :로드 시간이 너무 다르기 때문에 제 쿼리에 문제가 있습니까?

실제로 실행중인 시스템에서 모든 비동기식 DB 호출을 동기화 호출로 변경했으며 내 통계에서 볼 수있는 것은 시스템이 DB 호출의 50 % 속도 증가를 보았습니다. 이것은 SignalR을 통해 연결된 100-120 명의 현재 사용자가있는 시스템입니다. DB가 매우 무겁습니다.

+1

First vs. FirstAsync와 FindAsync를 비교할 수 있습니다. First와 Find는 꽤 다른 양의 일을합니다. – vittore

+0

또한 'Async'는 "빠름"이 아닙니다. 그것은 많은 오버 헤드를 추가합니다. 그러나 네트워크 통신을 기다리는 시간을 사용할 수 있습니다. – vittore

+0

Async/Await에 오버 헤드가 있다는 것을 알고 있지만 EF를 통한 SQL 호출이 2-4 배 느려질 것이라고 생각하지 않습니다. –

답변

0

자세한 내용은 this article에서 자세히 설명합니다.

비동기가 빠르지 않고 정상 "동기화"코드 위에 많은 오버 헤드가 추가됩니다. 하지만 대기 시간 낭비 (네트워크 연결 지연 등)가 많은 경우 리소스를 더 잘 사용할 수 있습니다.

관련 문제