web-dev-qa-db-fra.com

Utilisation de DbContext Définissez <T> () au lieu d’exposer sur le contexte

Y a-t-il des différences en procédant comme suit:

public class UsersContext : DbContext
{
    public DbSet<User> Users { get; set; }
}

par rapport à la méthode Set<T> du contexte:

public class UsersContext : DbContext
{
}

var db = new UsersContext();
var users = db.Set<User>();

Ceux-ci font effectivement la même chose, me donnant un ensemble d'utilisateurs, mais existe-t-il de grandes différences si ce n'est que vous n'exposez pas l'ensemble via une propriété?

22
Dismissile

La propriété Users est ajoutée pour plus de commodité. Vous n'avez donc pas besoin de vous rappeler toutes les tables et la classe correspondante. Vous pouvez utiliser Intellisense pour afficher toutes les tables avec lesquelles le contexte a été conçu. Le résultat final est fonctionnellement équivalent à utiliser Set<T>.

14
Servy

Vous bénéficiez d'un avantage avec l'ancienne méthode lorsque vous utilisez des migrations Code-First, car les nouvelles entités sont automatiquement détectées. Sinon, je suis presque certain qu'ils sont équivalents.

5
PinnyM

Je pense qu'il y a une certaine différence ..__ Laissez-moi utiliser l'exemple comme dans la question . Supposons que je veuille faire un Any basé sur User.FirstName et User.LastName

Méthode 1: UsersContext.Users.Any(u => u.FirstName.ToLower() == userObj.FirstName && u.LastName.ToLower() == userObj.LastName);

Méthode2: (UsersContext.Set(typeof(User)) as IQueryable<User>).Any(u => u.FirstName.ToLower() == userObj.FirstName && u.LastName.ToLower() == userObj.LastName);

J'ai vérifié dans SQL profiler la requête déclenchée dans Method1 est:

    exec sp_executesql N'SELECT 
CASE WHEN ( EXISTS (SELECT 
    1 AS [C1]
    FROM [dbo].[User] AS [Extent1]
    WHERE (((LOWER([Extent1].[FirstName])) = (LOWER(@p__linq__0))) AND ((LOWER([Extent1].[LastName])) = @p__linq__1)
)) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT 
    1 AS [C1]
    FROM [dbo].[User] AS [Extent2]
    WHERE (((LOWER([Extent2].[FirstName])) = (LOWER(@p__linq__0))) AND ([Extent2].[LastName] = @p__linq__1)
)) THEN cast(0 as bit) END AS [C1]
FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]',@p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000)',@p__linq__0=N'jack',@p__linq__1=N'saw'

De Method2:

    SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[FirstName] AS [FirstName], 
[Extent1].[LastName] AS [LastName], 
[Extent1].[Email] AS [Email], 
.......other fields......
FROM [dbo].[Users] AS [Extent1]

La table a 40000 enregistrements et Method1 prend environ 20 ms tandis que Method2 prend environ 3500 ms.

2
maicalal

C’est ainsi que j’ai configuré mon dbSet générique, fonctionne très bien

DbContext context = new MyContext();
DbSet<T> dbSet = context.Set<T>();

C’est la version générique de quelque chose de plus explicite, comme

DbContext context = new MyContext();
DbSet<User> dbSet = context.Set<User>();

Dans les deux cas, ils sont identiques (lorsque T est User)

2
Travis J

Je pense qu'il n'y a pas une telle différence entre deux approches, si ce n'est que Set<User>() convient mieux à la mise en œuvre de modèles d'accès aux données tels que le modèle Repository en raison de la nature générique de la méthode Set<T>().

0
Behnam Esmaili