在我的应用程序中,绝不能删除数据库中的数据。
实体有一个属性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查询中删除。
答案 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子句的查询。