usesqlserver optionsbuilder net dbcontextoptions dbcontextfactory context asp applicationdbcontext c# .net entity-framework ef-code-first dbcontext

c# - optionsbuilder - Usando DbContext Set<T>() en lugar de exponer en el contexto



optionsbuilder usesqlserver connection string (5)

¿Hay alguna diferencia al hacer lo siguiente?

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

versus usar el método Set<T> del contexto:

public class UsersContext : DbContext { } var db = new UsersContext(); var users = db.Set<User>();

Estos efectivamente hacen lo mismo, dándome un conjunto de Usuarios, pero ¿hay alguna diferencia diferente a la que usted no está exponiendo el conjunto a través de una propiedad?


Así es como configuro mi dbSet genérico, funciona bien

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

Es la versión genérica de algo más explícito, como

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

De cualquier manera, son los mismos (cuando T es User )


Creo que hay alguna diferencia. Déjame usar el ejemplo como en la pregunta. Supongamos que quiero hacer un Any basado en User.FirstName y User.LastName (la tabla de usuarios tiene más campos)

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

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

Verifiqué en el generador de perfiles SQL la consulta activada en el Método 1 es:

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 tabla tiene 40000 registros y Method1 toma alrededor de 20 ms, mientras que Method2 toma alrededor de 3500 ms.


Creo que no hay tal diferencia entre dos enfoques, excepto que Set<User>() es más adecuado para implementar patrones de acceso a datos como el patrón de Repository debido a la naturaleza genérica del método Set<T>() .


La propiedad Users se agrega para su conveniencia, por lo que no necesita recordar qué son todas sus tablas y cuál es la clase correspondiente, puede usar Intellisense para ver todas las tablas con las que el contexto fue diseñado para interactuar. El resultado final es funcionalmente equivalente a usar Set<T> .


Obtendrá un beneficio con el método anterior cuando use las migraciones de Code-First, ya que las nuevas entidades se detectarán automáticamente. De lo contrario, estoy bastante seguro de que son equivalentes.