使用索引器从数据存储中检索 Linq to SQL 对象
class UserDatastore : IUserDatastore
{
...
public IUser this[Guid userId]
{
get
{
User user = (from u in _dataContext.Users
where u.Id == userId
select u).FirstOrDefault();
return user;
}
}
...
}
我们团队中的一位开发人员认为,上述情况下的索引器并不合适,应该首选 GetUser(Guid id)
方法。
论据是:
1)我们没有索引到内存中的集合,索引器基本上执行隐藏的 SQL 查询 2) 在索引器中使用 Guid 是不好的(FxCop 也标记了这一点) 3) 从索引器返回 null
不是正常行为 4) API 用户通常不会期望任何这种行为,
我在一定程度上同意(大部分)这些观点。
但我也倾向于认为 Linq 的特征之一是抽象数据库访问,使您看起来只是在处理一堆集合,即使惰性求值范例意味着这些集合不会被求值直到您对它们运行查询。对我来说,以与这里的具体内存集合相同的方式访问数据存储似乎并不矛盾。
另请记住,这是一个继承的代码库,广泛且一致地使用此模式,是否值得重构?我承认从一开始就使用 Get 方法可能会更好,但我还不确信使用索引器是完全错误的。
我很想听听大家的意见,谢谢。
class UserDatastore : IUserDatastore
{
...
public IUser this[Guid userId]
{
get
{
User user = (from u in _dataContext.Users
where u.Id == userId
select u).FirstOrDefault();
return user;
}
}
...
}
One of the developers in our team is arguing that an indexer in the above situation is not appropriate and that a GetUser(Guid id)
method should be prefered.
The arguments being that:
1) We aren't indexing into an in-memory collection, the indexer is basically performing a hidden SQL query
2) Using a Guid in an indexer is bad (FxCop flagged this also)
3) Returning null
from an indexer isn't normal behaviour
4) An API user generally wouldn't expect any of this behaviour
I agree to an extent with (most of) these points.
But I'm also inclined to argue that one of the characteristics of Linq is to abstract the database access to make it appear that you're simply working with a bunch of collections, even though the lazy evaluation paradigm means those collections aren't evaluated until you run a query over them. It doesn't seem inconsistent to me to access the datastore in the same manner as if it was a concrete in-memory collection here.
Also bearing in mind this is an inherited codebase which uses this pattern extensively and consistently, is it worth the refactoring? I accept that it might have been better to use a Get method from the start, but I'm not yet convinced that it's completely incorrect to be using an indexer.
I'd be interested to hear all opinions, thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我倾向于同意您的团队开发人员建议的几乎所有内容,除了
Guid
部分。如果这里有任何问题,考虑到性能,它一定是在数据库级别,而不是在您的代码中。我个人认为属性和索引器不应该隐藏长时间运行的操作,尽管
用户
可以通过LINQ-to-SQL进行缓存。这就是为什么我也更喜欢一种方法。我也同意从索引器返回 null 是不好的。相反,抛出异常。
I tend to agree with almost everything your team developer suggested, except the
Guid
part. If there's any problem here, it must be at the database level considering performance, not in your code.Personally I think Properties and Indexers should not hide long running operations, although the
Users
could be cached by LINQ-to-SQL. That's why I would also prefer a method.I also agree that returning a null from an indexer is bad. Throw an exception instead.
我认为他关于使用 GUID 作为索引器的观点可能是指它存储在数据库中。使用整数作为键将提供更好的性能,并且比使用 GUID 占用更少的存储空间。
返回 null 的情况非常罕见,因为通常使用索引器时,如果索引(键)不在集合中,您将抛出异常。
就我个人而言,我并没有真正看到这里的问题,它几乎相当于有一个
GetUser
方法。我的意思是,如果您想稍微整理一下,您实际上可以引入一个名为GetUser
的私有方法,索引器可以调用该方法,例如从设计的角度来看,我个人不会使用索引器,我会使用
GetUser
方法。I think his point regarding using a GUID as an indexer is probably referring to it being stored in the Database. Using an integer as the key would provide better performance and would take up less storage than using GUIDs.
Returning null is quite uncommon as usually with an indexer if the index (key) is not in the collection you would throw an exception instead.
Personally I don't really see the issue here it is pretty much the equivalent of having a
GetUser
method anyway. I mean if you wanted to tidy it up a bit you could actually introduce a private method calledGetUser
that the indexer could call e.g.Looking from a design point of view, personally I would not have used an Indexer, I would have went with a
GetUser
method.