简体   繁体   English

Linq to SQL Repository~theory~ - Generic但现在使用Linq到Objects?

[英]Linq to SQL Repository ~theory~ - Generic but now uses Linq to Objects?

The project I am currently working on used Linq to SQL as an ORM data access technology. 我目前正在开发的项目使用Linq to SQL作为ORM数据访问技术。 Its an MVC3 Web app. 它是一个MVC3 Web应用程序。 The problem I faced was primarily due to the inability to mock (for testing) the DataContext which gets autogenerated by the DBML designer. 我遇到的问题主要是由于无法模拟(测试)由DBML设计器自动生成的DataContext。

So to solve this issue (after much reading) I refactored the repository system which was in place - single repository with seperate and duplicated access methods for each table which ended up with something like 300 methods only 10 of which were unique - into a single repository with generic methods taking the table and returning more generic types to the upper reaches of the application. 因此,为了解决这个问题(经过多次阅读),我重构了存储库系统 - 单个存储库,每个表具有单独的和重复的访问方法,最终只有300个方法,其中只有10个是唯一的 - 进入单个存储库使用泛型方法获取表并将更多泛型类型返回到应用程序的上游。 The DataContext is now wrapped, and easily mocked. DataContext现在被包装,并且很容易被模拟。

[Edit: To achieve this i have used the link provided by Jacob below, coincidently!] [编辑:为了达到这个目的,我已经使用了下面雅各布提供的链接,巧合!]

My question revolves more around the design I've used to get thus far and the differences I'm noticing in the structure of the app. 我的问题更多地围绕着我迄今为止所获得的设计以及我在应用程序结构中注意到的差异。

1) Having refactored the code which used classic Linq to SQL queries: 1)重构了使用经典Linq到SQL查询的代码:

    public Billing GetBilling(int id)
    {
        var result = (
        from bil in _bicDc.Billings
        where bil.BillingId == id
        select bil).SingleOrDefault();
        return (result);
    }

it now looks like: 它现在看起来像:

    public T GetRecordWhere<T>(Expression<Func<T, bool>> predicate) where T : class
    {
        T result;
        try
        {
            result = _dataContext.GetTable<T>().Where(predicate).SingleOrDefault();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return result;
    }

and is used by the controller with a query along the lines of: 并由控制器使用,其查询方式如下:

_repository.GetRecordWhere<Billing>(x => x.BillingId == 1);

which is fine, and precisely what I wanted to achieve. 这很好,而且正是我想要达到的目标。

...however.... I'm also having to do the following to get precisely the result set i require in the controller class (the highest point of the app in essence)... ...但是......我还必须做以下操作才能准确地获得控制器类中所需的结果集(本质上是应用程序的最高点)......

viewModel.RecentRequests = _model.GetAllRecordsWhere<Billing>(x => x.BillingId == 1)
                .Where(x => x.BillingId == Convert.ToInt32(BillingType.Submitted))
                .OrderByDescending(x => x.DateCreated).
                Take(5).ToList();

This - as far as my understanding is correct - is now using Linq to Objects rather than the Linq to SQL queries I was previously? 这 - 就我的理解是正确的 - 现在使用Linq to Objects而不是之前使用的Linq to SQL查询? Is this okay practise? 这可以吗? It feels wrong to me but I dont know why. 我感觉不对,但我不知道为什么。 Probably because the logic of the queries is in the very highest tier of the app, rather than the lowest, but... I defer to you good people for advice. 可能是因为查询的逻辑位于应用程序的最高层,而不是最低层,但是...我会向您推荐好人。 One of the issues I considered was bringing the entire table into memory but I understand that using the Iqeryable return type the where clause is taken to the database and evaluated there. 我考虑的一个问题是将整个表放入内存,但我知道使用Iqeryable返回类型将where子句带到数据库并在那里进行评估。 Thus returning only the resultset i require... i may be wrong. 因此只返回我需要的结果集...我可能是错的。

And if you've made it this far, well done. 如果你已经做到这一点,做得好。 Thank you, and if you have any advice it is very much appreciated!! 谢谢,如果您有任何建议,非常感谢!!

Update: Inclusion of GetAllRecordsWhere method as requested 更新:根据请求包含GetAllRecordsWhere方法

    public IQueryable<T> GetAllRecordsWhere<T>(Expression<Func<T, bool>> predicate) where T : class
    {
        return _dataContext.GetTable<T>().Where(predicate);
    }

which uses: 使用:

    public IQueryable<TName> GetTable<TName>() where TName : class
    {
        return _db.GetTable<TName>().AsQueryable();
    }

If _model.GetAllRecordsWhere returns an IQueryable then your subsequent querying is still just building up an expression tree (which is what i think you mean by using LinqToSql), it only gets turned into SQL an executed when you enumerate the collection by iterating over it or calling ToList() or ToArray(). 如果_model.GetAllRecordsWhere返回一个IQueryable,那么你的后续查询仍然只是构建一个表达式树(我认为你的意思是使用LinqToSql),它只会在你通过遍历它来枚举集合时变成执行的SQL或者调用ToList()或ToArray()。

As an aside don't do this: 暂且不要这样做:

catch (Exception ex)
{
    throw ex;
}

All you are doing is swallowing the stack trace. 你所做的就是吞下堆栈痕迹。 If you want to rethrow an exception just call throw , never throw ex . 如果你想重新抛出异常只是调用throw ,永远不要throw ex If you don't do anything in your catch other than rethrow then don't catch. 如果除了重新抛出之外你没有在捕获物中做任何事情,那么就不要抓住了。 The nowmal pattern for this would be catch, do some logging, rethrow. 现在的模式是捕获,做一些记录,重新抛出。

Here is a good article that explains how to mock out your DataContext: 这是一篇很好的文章,解释了如何模拟你的DataContext:

Faking your LINQ provider part 1 伪造LINQ提供程序第1部分

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM