实体框架LINQ to SQL翻译:它是如何工作的?

时间:2015-09-25 12:53:32

标签: c# entity-framework

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

实体有一个属性Deleted,可以设置为true或false。

虚拟删除的实体无法从数据库中删除,从应用程序的角度来看它们不一定存在。

我通过在数据访问层中创建GetAll-方法(例如GetAllUsers)来管理它。这些方法只返回flaged为NOT NOT(!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));
}

这种架构非常好,因为我确信我总是提取未删除的实体,但我担心这样做效率不高。

我的问题非常简单:我的应用程序是每次请求特定用户时从User表(select * from User)中提取所有数据,还是实体框架足够智能以了解我想要的内容并转换为SQL查询类似:select * from User where userName = @userName

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

4 个答案:

答案 0 :(得分:6)

  

是我的应用程序在每次请求特定用户时从User表(select * from User)中提取所有数据,或者Entity Framework足够聪明,可以理解我想要的内容,并且构建的SQL查询类似于:{{ 1}}?

您正在检索每次都未删除的所有用户。原因是select * from User where userName = @userName会返回GetAllUsers而不是IEnumerable<User>,因此您有离开了Linq-to-EF的世界,现在正在使用Linq-to-objects,它在内存中进行所有过滤,排序等工作,不会返回数据库。

好的新闻是您可以轻松地重构此内容,而无需将返回类型更改为IQueryable<user>并可能破坏现有代码:

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)); } 只是在原始查询中附加一个条件,因此操作将被推送到数据库而不是在内存中过滤。

答案 1 :(得分:1)

是的,Entity Framework为您的查询创建一个SQL语句。

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

N.B。您仍然可以插入新行。

CREATE VIEW UsersActive
AS
SELECT *
FROM Users
WHERE Deleted != 1

然后在您的实体上:

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

答案 2 :(得分:0)

是的,对于每个用户,它将从数据库中请求它,如果您想避免与数据库交互,那么您可以缓存用户表,然后您可以根据用户名从该缓存对象中获取用户

答案 3 :(得分:0)

我会将GetUserById函数更改为此,以确保正确的SQL查询:

public User GetUserById(string userName)
{
    return _dataContext.FirstOrDefault(elt => elt.UserName.Equals(userName) && !elt.Deleted);
}

这应该生成一个带有适当where子句的查询。