C# 使用DbContext集<;T>;()而不是暴露在上下文中
执行以下操作时是否存在任何差异:C# 使用DbContext集<;T>;()而不是暴露在上下文中,c#,.net,entity-framework,ef-code-first,dbcontext,C#,.net,Entity Framework,Ef Code First,Dbcontext,执行以下操作时是否存在任何差异: public class UsersContext : DbContext { public DbSet<User> Users { get; set; } } public类用户上下文:DbContext { 公共数据库集用户{get;set;} } 与使用上下文的Set方法相比: public class UsersContext : DbContext { } var db = new UsersContext(); var us
public class UsersContext : DbContext
{
public DbSet<User> Users { get; set; }
}
public类用户上下文:DbContext
{
公共数据库集用户{get;set;}
}
与使用上下文的Set
方法相比:
public class UsersContext : DbContext
{
}
var db = new UsersContext();
var users = db.Set<User>();
public类用户上下文:DbContext
{
}
var db=新用户上下文();
var users=db.Set();
这些方法有效地实现了同样的功能,为我提供了一组用户,但除了不通过属性公开该组用户之外,还有什么大的区别吗?在使用代码优先迁移时,前一种方法会带来好处,因为新实体将自动检测到。否则,我很确定它们是等效的。我认为这两种方法之间没有这样的区别,除了
Set()
更适合实现像Repository
这样的数据访问模式,因为Set()
方法的泛型本质。这就是我设置泛型dbSet的方式,很好用
DbContext context = new MyContext();
DbSet<T> dbSet = context.Set<T>();
DbContext context=newmycontext();
DbSet DbSet=context.Set();
它是更明确的东西的通用版本,例如
DbContext context = new MyContext();
DbSet<User> dbSet = context.Set<User>();
DbContext context=newmycontext();
DbSet DbSet=context.Set();
无论哪种方式,它们都是相同的(当
T
是User
时)添加Users
属性是为了方便,因此您不需要记住所有表是什么以及对应的类是什么,您可以使用Intellisense查看上下文设计用于交互的所有表。最终结果在功能上等同于使用Set
我认为有一些区别。
让我用问题中的例子。
假设我想基于User.FirstName和User.LastName执行Any(User表有更多字段)
方法1:UsersContext.Users.Any(u=>u.FirstName.ToLower()==userObj.FirstName&&u.LastName.ToLower()==userObj.LastName)代码>
方法2:(UsersContext.Set(typeof(User))为IQueryable).Any(u=>u.FirstName.ToLower()==userObj.FirstName&&u.LastName.ToLower()==userObj.LastName)代码>
我签入了sql探查器Method1中激发的查询是:
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'
方法2:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FirstName] AS [FirstName],
[Extent1].[LastName] AS [LastName],
[Extent1].[Email] AS [Email],
.......other fields......
FROM [dbo].[Users] AS [Extent1]
该表有40000条记录,Method1大约需要20毫秒,Method2大约需要3500毫秒。一个区别是Set方法采用任何类型,包括非实体,它不会抛出异常,只返回该类型的空集。因此,如果键入错误的类名,您可能会陷入困境。我没有想到迁移!是的,我知道通用存储库的用途在哪里,但我很好奇它是否有缺点。呃……好吗?我理解它是如何工作的。我想知道区别/限制是什么。@Dismissible-没有限制或区别,只是您可以通过使用泛型定义并传入类型来保存一些重复的代码。Set应该是return always single instance,以说明没有限制或区别,对吗?查看反编译的源代码,DbSet在DbContext的每个实例中都是相同的实例(例如,如果多次调用context.Set(),则会得到对相同DbSet的相同引用,假设“context”从未更改过实例)。这是在DbContext内部的InternalContext中完成的(它使用类型作为键保存一个内部字典)。@abatishchev Nope有一个Set methodSet可以接受一个泛型参数。Try Set().Any(…)@Dismissile我试过Set().Any(),它有同样的行为。你当时做了一件非常奇怪的事情,因为这三个方法都为我生成了相同的查询。@Dismissile你是对的。我发现了奇怪的部分。在Method2的情况下,即Set().Any(…),我传递的表达式类似于ValidationMethod(u=>u.FirstName.ToLower()==userObj.FirstName&&u.LastName.ToLower()==userObj.LastName)
此实习生将执行Set().Any(…表达式作为参数传递)
不确定确切原因。还在找呢。Will update.am跟踪问题用户只能是一个实例,而在上下文中,我想知道Set方法,是否也返回单个实例?您想要哪一个?您可以使用System.Linq.Dynamic。db.Set().Single(“Id=@0”,someId);只要主键是用户对象或您查询的任何对象上的Id。