类构造函数与使用语句进行数据库连接

时间:2014-12-10 10:25:31

标签: c# asp.net-mvc entity-framework constructor

我有两个场景(下面的示例),两者都是完全合法的数据库请求方法,但是我不确定哪个是最好的。

示例一 - 这是我们在构建新应用程序时通常使用的方法。

private readonly IInterfaceName _repositoryInterface;

public ControllerName()
{
    _repositoryInterface = new Repository(Context);
}

public JsonResult MethodName(string someParameter)
{
    var data = _repositoryInterface.ReturnData(someParameter);
    return data;
}

protected override void Dispose(bool disposing)
{
    Context.Dispose();
    base.Dispose(disposing);
}

public IEnumerable<ModelName> ReturnData(filter)
{
    Expression<Func<ModelName, bool>> query = q => q.ParameterName.ToUpper().Contains(filter)

    return Get(filter);
}

示例二 - 我最近开始更频繁地看到这个

using (SqlConnection connection = new SqlConnection(
        ConfigurationManager.ConnectionStrings["ConnectionName"].ToString()))
{
    var storedProcedureName = GetStoredProcedureName();

    using (SqlCommand command = new SqlCommand(storedProcedureName, connection)) 
    {
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add("@Start", SqlDbType.Int).Value = start;

        using (SqlDataReader reader = command.ExecuteReader())
        {
            // DATA IS READ AND PARSED
        }
    }
}

两个示例都以某种形式使用Entity Framework(第一个比另一个更多),每个表都有可以查询的模型和映射文件。第二个例子对第一个例子做的主要事情(关于EF)是利用Migrations作为存储过程代码生成的一部分。另外,两者都实现了类似于下面第二个链接中的Repository模式。

Code First - MSDN Contoso University - Tutorial

我对示例一的理解是,一旦调用Controller,就会实例化存储库和上下文。在对存储库进行调用时,它返回数据但保留上下文,直到在方法结束时将其丢弃。另一方面,示例二将在数据库调用结束后立即调用Dispose(除非强制进入内存,例如在.ToList()上使用IEnumerable)。如果我的理解不正确,请在适当的地方纠正我。

所以我的主要问题是使用一个而不是另一个的缺点和优点是什么?例如,与示例1相比,使用示例2会有更大的性能开销。

仅供参考:我试图寻找下面的答案,但一直没有成功,所以如果你有类似的问题,请随时指出我的方向。

2 个答案:

答案 0 :(得分:2)

您似乎正在进行这样的比较:

  

建造房屋或在浴室安装管道是否更好?

你可以同时拥有两者。您可以拥有一个使用数据连接(管道)的存储库(house),因此它不是“OR”情况。

ReturnData的来电没有理由不使用SqlCommand

现在,值得考虑的真正重要的不同之处在于存储库是否拥有一个资源(内存,连接,管道,文件等)在其生命周期内打开,或者只是每次数据调用。

使用using的优点是资源仅在呼叫期间打开。这对缩放应用程序非常有帮助。

另一方面,打开连接会产生开销,所以最好 - 特别是对于单线程应用程序 - 打开连接,执行多个任务,然后关闭它。

所以它真的归结为你正在编写什么类型的应用程序,你使用哪种方法。

答案 1 :(得分:1)

你的第二个例子是不使用实体框架。看来你可能有两种不同的数据访问方法,虽然很难从存储库片段中分辨出来,因为它非常正确地隐藏了数据访问实现。第二个示例正确地使用“using”语句,就像在任何实现IDisposable的对象上一样。这意味着您不必担心调用dispose。这是使用纯粹的ADO.net,这是实体框架在幕后使用的。

如果第一个示例正在使用Entity框架,那么您很可能在游戏中使用延迟加载,在这种情况下,您需要保留DbContext直到执行查询。实体框架是一种ORM工具。它也使用引擎盖下的ADO.net连接到数据库,但它也提供了更多的顶部。关于这两个主题的好书应该可以帮到你。

我发现学习ADO.net首先有助于理解Entity Framework如何从数据库中检索信息。

using语句是一种很好的做法,你找到一个实现IDisposable的对象。您可以在此处详细了解:IDisposable the right way

为了回应问题的变化 - 答案仍然总体上保持不变。在性能方面 - 查询返回的速度有多快?一个人的表现比另一个好吗?只有您当前的系统和设置可以告诉您。这两种方法似乎都是以正确的方式做事。

我没有使用迁移,因此不确定为什么要获得与EF模型集成的ADO.net类型查询,但不会对此功能感到惊讶。我体验过的实体框架会为您创建查询,然后使用第二个示例中的ADO.net对象执行它们。关键是你想要为SqlConnection和SqlCommand对象使用“using”块(虽然我认为你不需要嵌套它们。外部“using block”中的所有内容都将被处理掉。)

没有什么可以阻止你在你的存储库中围绕上下文放置一个“使用”块,但是当它延迟加载相关实体时,你会得到一个错误,因为上下文将被处理掉。如果需要进行此更改,可以在查询中包含相关元素,并取消延迟加载方法。在某些情况下,这样做可以提高性能,但您需要在系统性能方面进行平衡。