Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架LINQ到SQL的转换:它是如何工作的?_C#_Entity Framework - Fatal编程技术网

C# 实体框架LINQ到SQL的转换:它是如何工作的?

C# 实体框架LINQ到SQL的转换:它是如何工作的?,c#,entity-framework,C#,Entity Framework,在我的应用程序中,决不能删除数据库中的数据 实体有一个属性“已删除”,该属性可以设置为true或false 实际上被删除的实体不能从数据库中删除,它们不能从应用程序的角度存在 我通过在数据访问层中创建GetAll方法(例如GetAllUsers)来管理这一点。这些方法仅返回伪装为未删除(!deleted)的实体,以及使用这些方法检索数据的所有其他方法(例如GetUserById) 请参见下面的示例 public IEnumerable<User> GetAllUsers() {

在我的应用程序中,决不能删除数据库中的数据

实体有一个属性“已删除”,该属性可以设置为true或false

实际上被删除的实体不能从数据库中删除,它们不能从应用程序的角度存在

我通过在数据访问层中创建GetAll方法(例如GetAllUsers)来管理这一点。这些方法仅返回伪装为未删除(!deleted)的实体,以及使用这些方法检索数据的所有其他方法(例如GetUserById)

请参见下面的示例

public IEnumerable<User> GetAllUsers()
{
    return _dataContext.Users.Where(element => !element.Deleted);
}

public User GetUserById(string userName)
{
    return GetAllUsers().FirstOrDefault(elt => elt.UserName.Equals(userName));
}
public IEnumerable GetAllUsers()
{
返回_dataContext.Users.Where(element=>!element.Deleted);
}
公共用户GetUserById(字符串用户名)
{
返回GetAllUsers().FirstOrDefault(elt=>elt.UserName.Equals(UserName));
}
从可靠性的角度来看,这种体系结构非常好,因为我确信我总是提取未删除的实体,但我担心这是不高效的

我的问题很简单:我的应用程序是否在每次请求特定用户时都从用户表中提取所有数据(
select*from User
),或者Entity Framework是否足够聪明,能够理解我想要什么,并转换为类似以下内容的SQL查询:
select*from User where userName=@userName


如果每次需要单个用户时都从数据库中提取所有数据,那么如何更改代码以创建正确的查询?我想保持集中,这样我就不必指定了!在每个LINQ查询中删除。

是的,实体框架为您的查询创建SQL语句

关于删除的行问题,您可以创建一个SQL视图,并将实体映射到该视图,而不是实际的表。这样,您就不太可能选择已删除的行

注意:您仍然可以插入新行

CREATE VIEW UsersActive
AS
SELECT *
FROM Users
WHERE Deleted != 1
然后在您的实体上:

[Table("UsersActive")]
public class User
{
    ...
}

是的,对于每个用户,它都会从数据库中请求,如果您想避免与数据库交互,那么您可以缓存用户表,然后您可以根据用户名从缓存对象中获取用户,我会将
GetUserById
函数改为此,以确保正确的SQL查询:

public User GetUserById(string userName)
{
    return _dataContext.FirstOrDefault(elt => elt.UserName.Equals(userName) && !elt.Deleted);
}
这将生成一个带有适当where子句的查询

每次请求特定用户时,我的应用程序是否从用户表中提取所有数据(
select*from User
),或者实体框架是否足够聪明,能够理解我需要什么,并且生成的SQL查询类似于:
select*from User where userName=@userName

您每次都在检索未被删除的所有用户。原因是
GetAllUsers
返回一个
IEnumerable
,而不是
IQueryable
,因此您将Linq的世界留给了EF,现在正在使用Linq to objects,它执行所有过滤、排序和,等,而不会返回到数据库

好消息是,您可以轻松地重构它,而无需将返回类型更改为
IQueryable
,也无需破坏现有代码:

// make the base query private   
private IQueryable<User> GetAllUsersQuery()
{
    return _dataContext.Users.Where(element => !element.Deleted);
}

public IEnumerable<User> GetAllUsers()
{
    return GetAllUsersQuery().AsEnumerable();
}

public User GetUserById(string userName)
{
    return GetAllUsersQuery().FirstOrDefault(elt => elt.UserName.Equals(userName));
}
//使基查询私有化
私有IQueryable GetAllUsersQuery()
{
返回_dataContext.Users.Where(element=>!element.Deleted);
}
公共IEnumerable GetAllUsers()
{
返回GetAllUsersQuery().AsEnumerable();
}
公共用户GetUserById(字符串用户名)
{
返回GetAllUsersQuery().FirstOrDefault(elt=>elt.UserName.Equals(UserName));
}

现在
GetUserByID
只需在原始查询上附加一个条件,这样操作将被推送到数据库,而不是在内存中进行过滤。

返回_dataContext.Users.firstOrdfoult(elt=>elt.UserName.Equals(UserName));这段代码不会达到您期望的效果。它将加载内存中所有未删除的记录,因为您返回的是
IEnumerable
,而不是
IQueryable
。是的,这就是我现在要做的。我不喜欢的是它容易出错:我总是要记住只提取未删除的实体。我想要所有其他方法都使用的集中式方法。使用多个
Where
语句、select或
FirstOrDefault
——只要所有方法都返回
IQueryable
,而不是
IEnumerable
,这没有什么错。事实上,这是一个常见的LINQ用例。原始代码的问题是它返回一个IEnumerableBreaking现有代码在这种情况下是一件好事。我怀疑OP是否想在内存中加载所有条目。但考虑到IQueryable很容易转换为IEnumerable,突破性的更改将非常复杂few@PanagiotisKanavos将返回类型更改为
IQueryable
可能会产生显著的意外副作用,直到运行时才会知道。如果调用方尝试附加无法转换为SQL的条件,则应用程序将在运行时失败。将返回类型保持为
IEnumerable
将防止出现这种情况。在
IQueryable
之上的任何过滤都应该在存储库IMHO中完成。感谢您的解释。这个答案是我比较喜欢的,但我必须确保它是正确的。如果您提供了一个源代码或有更多的开发人员确认您所写的内容,我可以将此答案标记为正确的anwser。@ErroreFatale为什么不亲自验证它?获取EF SQL探查器,查看在这两种情况下都创建了哪些查询。我不介意你被警告,但我不确定我会再信任这个网站上的三张海报而不是一张。@ErroreFatale你也可以从答案中验证它,否,EF只会为
GetAllUsers
创建一个查询。由于该方法返回一个
IEnumerable
,因此
GetUserById
中的额外过滤将在内存中完成。我认为这不正确
IEnumerable
只是一个接口,而不是类型。除非你明确要求