WebMatrix的数据访问选择

当WebMatrix最初推出时,它会从代码文件中查看原始SQL语句的人刺激了很多活动,或者谁感知使用动态对象的问题。其中一些人在恐怖和发誓或越过他们的不满,而其他人则感受到了对...做一些事情的冲动"problem"正如他们所看到的那样,并导致了许​​多开源数据访问项目。我很快就会看看三个项目,看看他们可能带来党的内容。

首先 - 一点上下文。 WebMatrix数据访问基于名为webmatrix.data的库。当整个东西中,它最初被称为Microsoft.data。 WebMatrix.data的主要特征是它与原始SQL合作。取决于您对等的围栏的哪一侧,这都是一个"good thing" and a "bad thing"。网页框架设计背后的核心原则之一是保持"concept count"低的。微软通过研究知道,ASP.NET可能是对知之甚少服务器侧网开发的人的挫败经验。在Web表单框架中,有大量的新事物可以了解哪些是外部给所有其他框架,例如ViewState,页面生命周期,事件模型等。 MVC是一款先进的架构,旨在易于进行可测试性,对担忧的分离以及您有很多学习,如果您现在的所有唯一编程经验都是Excel中的奇怪功能。例如,如果看经典ASP和PHP,则会获得完全不同的体验。在最简单的级别,数据访问通常是通过对数据库中的数据库的直接调用来执行,该数据库显示编程逻辑和HTML的混合,并且对于相对简单的站点,这是可接受的。有大量的"simple"在那里的网站,很多人只想建造这样的简单网站。它们不需要MVC的建筑点缀。不是每个网站都是一个"软件工程项目"。但关键是,如果您只是学习如何构建动态网站,请在SQL上找到帮助很简单。网上有数百万个SQL示例。

另一方面,复杂的网站(应用程序,真的)需要仔细攻击。许多博主在这些项目中全职工作,并了解用HTML和内联SQL混合逻辑的陷阱 在这些项目中. They know, for example, that they do not want to have to change code all over the application if a field name changes in the database. And they know that applying automated tests to this type of project is nearly impossible. Some of these people have forgotten (it seems to me) about the other side of web development, or what it was like when they first started out. They think that every web site is indeed a 软件工程项目, and all should follow "best practice",虽然这取决于您的观点。但是,它通常同意,在这些类型的项目中包含内联SQL不是最好的做法。

我看过的三个项目是:

截至目前,它们处于不同程度的完整性。但它们都通过Web页面包管理器提供。如果您想自己与他们一起玩,您需要确保您选择"Default (All)"作为您的来源选项。如果有任何包在某些阶段将其视为默认列表,则会有趣。

每个软件包都提供不同的问题的不同解决方案。因此,它们中的每一个都有自己的一组特征,要么拥抱webmatrix.data,或完全替换它。我会先看看Jeremy Skinner的图书馆。

webmatrix.data.stronglytyped

jeremy主要想要解决的问题是webmatrix.data返回一个动态对象。动态类型在C#4.0中是新的,并提供一些巨大的好处,但有一些缺点。有一件事,你会失去任何编译时间检查和智能敏感。对于大多数WebMatrix用户,这将不会是一个问题。 WebMatrix本身在此领域没有提供功能(在V 1.0中),但如果您决定在主菜单中使用“启动”按钮在Visual Web开发人员或Visual Studio中打开您的网站,则新的信息世界等待您。当您将鼠标悬停在代码中时,工具提示为您提供有关它们的更多信息,并且显示下拉列表允许您选择已知对象曝光的属性和方法。使用webmatrix.data运行查询时,将从生成的数据动态创建对象。对象填充了属性,该属性由返回数据附带的架构信息生成。这很棒,因为您可以处理数据库字段名称,就像它们实际上是类型上的属性一样。但由于在制作数据库调用之前不存在属性,因此在键入代码时,没有帮助可以告诉您"property"您当前正在引用代码中实际在运行时存在。这是一个典型的webmatrix.data示例:

@{
    var db = Database.Open("Northwind");
    var sql = "Select * From Products Where CategoryId = @0 Order By ProductName";
    var products = db.Query(sql, 4);
}

@foreach(var product in products){
    @Product.ProductName.<br />
}

数据库中的产品表中有一个字段"ProductName", but when you type Product.ProductName.,webmatrix(或c#编译器,真的)不知道。你可以轻松地键入 product.productsname. (notice the extra "s"),在您运行页面之前,您将不会被告知任何错误。你键入(在VS中)的所有所有人都被告知 产品名称 是一个动态表达式,它将在运行时解决。 WebMatrix.data.stronglytyped是webmatrix.data周围的包装器,它使您可以将动态类型转换为强类型对象。您需要在类中定义强类型对象,但这很简单。以下是显示产品类定义以匹配数据库表的一个:

using System;

/// <summary>
/// Summary description for Product
/// </summary>
public class Product
{
    public int ProductID { get; set; }
    public string 产品名称 { get; set; }
    public int SupplierID { get; set; }
    public Category Category { get; set; }
    public string QuantityPerUnit { get; set; }
    public decimal UnitPrice { get; set; }
    public Int16 UnitsInStock { get; set; }
    public Int16 UnitsOnOrder { get; set; }
    public Int16 ReorderLevel { get; set; }
    public bool Discontinued { get; set; }

}

现在,当您使用webmatrix.data.stronglytyped时,您可以将查询的结果投影为一系列产品对象:

@{
    var db = Database.Open("Northwind");
    var products = db.Query<Product>("Select * From Products Where CategoryID = @0", 4);
}
        

@foreach(var product in products){
    @Product.ProductName.<br />
}

当您在产品后键入点时,IntelliSense提供了您可以使用的类中定义的属性列表。没有拼写错误的运行时错误。但是这个图书馆有帮​​助。让"■假设您想要销售所有具有较少单位的产品,而不是重新排序级别。使用webmatrix.data,有几种方法可以这样做。您可以更改SQL以对字段值执行计算,并返回一个附加列的数据列,这将成为动态对象上的其他属性 - 具体取决于您的数据库支持的功能。或者您可以在剃刀代码中为其提供有条件:

 
@foreach(var product in products){
    if(product.UnitsInStock < product.ReorderLevel){
        @Product.ProductName.<br />
    }
}

现在没关系,但如果条件变得更加复杂,或者你需要在多页上应用这个测试?您的剃刀代码将开始变得越来越少。 WebMatrix.data.stronglytytyped答案此问题是因为它允许您在对象上定义其他属性,因此您可以使用其他属性增强您的产品类:

public class Product
{
    public int ProductID { get; set; }
    public string 产品名称 { get; set; }
    public int SupplierID { get; set; }
    public Category Category { get; set; }
    public string QuantityPerUnit { get; set; }
    public decimal UnitPrice { get; set; }
    public Int16 UnitsInStock { get; set; }
    public Int16 UnitsOnOrder { get; set; }
    public Int16 ReorderLevel { get; set; }
    public bool Discontinued { get; set; }
    public bool 肩膀 { 
       get { return UnitsInStock < ReorderLevel ? 真的 : 错误的; } 
    }

 

创建产品对象时,它们现在有一个 肩膀 财产 which will be 真的 或者 错误的,取决于另外两个字段之间的比较。当然,该物业出现在IntelliSense中。如果,之后,您还想考虑单位的数量,以确定产品是否已达到新订单的点,只需在一个地方更改代码。

webmatrix.data.stronglytypey不会改变您使用webmatrix.data的事实。你真的不需要学习任何新的东西来使用它。您仍然使用SQL和标准WebMatrix.data.database方法。这意味着可以使用SQL中的熟悉连接来导航关系。请注意,产品类有类别属性?这是在单独的类中定义的:

/// <summary>
/// Summary description for ClassName
/// </summary>
public class Category
{
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }
    public string Description { get; set; }
    public byte[] Image { get; set; }
    public int TotalProducts { get; set; }
}

这反映了数据库中的类别表,但具有额外的属性,称为总产品。如果您想要按类别获取产品总数,则只需执行以下操作:

@{
    var db = Database.Open("Northwind");
    var categories = db.Query<Category>(@"SELECT CategoryName, Count(Products.CategoryID) AS TotalProducts FROM Products
                    INNER JOIN Categories ON Categories.CategoryID = Products.CategoryID GROUP BY CategoryName");
}

将结果写入浏览器同样简单:

@foreach(var category in categories){
    @:@category.CategoryName (@category.TotalProducts)<br />
}

大量的

Rob Conery已经稍微接近了一些东西。大规模库(它是一个C#代码文件)不使用WebMatrix.data。它取代了它。它基于活动记录模式,它将底层数据库表视为基于列名的具有属性的对象。当从数据库检索数据时,动态生成对象上的属性。对于WebMatrix.Data.stronglytyped,没有正式定义对象。到目前为止,在生成对象和属性的情况下,大规模和WebMatrix之间的差异很小,但是大量的也在这些对象上提供了许多方法,例如All,插入,更新,删除等,这更多活动记录模式的特征。

使用Massive时,您需要在Web.config文件中定义连接字符串。 WebMatrix团队对Web.config文件屏蔽了很多才能屏蔽初学者,但是使用其他任何其他vasp.net的任何人都将熟悉它们。它们包含应用程序的常规设置和配置。将新文件添加到WebMatrix时,请选择"Suggested" or "All"选项并查找web.config(4.0)。这是添加连接字符串的内容。请注意,连接字符串已提供一个名称:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="真的" targetFramework="4.0"/>
  </system.web>
  <connectionStrings>
    <add name="northwind" connectionString="Data Source=|DataDirectory|Northwind.sdf;" providerName="System.Data.SqlServerCe.4.0" />
  </connectionStrings>
</configuration>

| DataDirectory | 部分是ASP.NET默认情况下的替换字符串,该字符串默认在网站内的App_Data文件夹中知道点。

您需要设置别的东西以进行大规模,这是映射到数据库表的对象的定义。以下代码映射到产品表:

using 大量的;
public class Products : DynamicModel {
    public Products() : base("northwind") {
        PrimaryKeyField = "ProductID";
    }
}

这与webmatrix.data.stronglytypey不那么涉及。它映射主键字段,并将连接字符串的名称传递到大规模。当我键入时,似乎是一个 更新到大规模 这意味着不需要连接字符串。 Massive将查找Web.config文件中的第一个连接字符串,但更改尚未推出到Nuget。您的产品类从DynamicModel继承(即冒号为for),这是一个实际上包含插入,所有,更新等方法的定义的对象。在第一个示例中,我们使用SQL获得了4个类别的所有产品。您可以通过使用其查询方法来完全相同的情况:

@{
    var Products = new Products();
    var products = Products.Query("Select * From Products Where CategoryId = @0 Order By ProductName", 4);
}

或者,您可以使用所有方法并通过某些可选参数:

@{
    var Products = new Products();
    var products = Products.All(where: "CategoryID = @0", args: 4);
}

这将动态构建SQL,使用参数来防止任何机会的SQL注入的威胁。所有方法都将返回整个表,因此它的选择相当于select *。但是,每种方法都通过IntelliSense获得,一旦您了解了方法所做的操作以及他们接受的参数,可以帮助节省一些时间。没有那么多,所以它不应该花很长时间。如果您只想返回某些列,您可以随时退回SQL语句。再次,最新更新将介绍另一个参数: ,您只能通过您要返回的列。返回类型是动态的,因此您没有IntelliSense或编译时间类型在Visual Studio中检查。如果您想返回每个类别的产品总数,则SQL可能是最佳方式:

@{
    var 类别 = new 类别();
    var categories = Categories.Query(@"SELECT CategoryName, Count(Products.CategoryID) AS TotalProducts FROM Products
                    INNER JOIN Categories ON Categories.CategoryID = Products.CategoryID GROUP BY CategoryName");
}

大量的也支持事务,这意味着如果您想连续执行多个命令,但只希望他们成功,如果所有人都成功,您可以这样做。

如果您使用SQL快乐,使用大规模似乎很少。它是主要的景点是转换为场景后面的SQL命令的方法集。如果您想直接移开SQL,这是一个很好的小工具。

simple.data.

我将通过指出这个图书馆处于早期阶段,刚刚达到0.5版,我将开始。它不完整。该库再次遵循主动记录模式,并尝试为初学者提供相对简单的方法,以便在未在其代码中插入SQL的情况下访问数据,这是Mark感觉只是"wrong"。它似乎错误地认为webmatrix.data没有提供对参数的任何支持(这是这样做),但尽管如此,如果您将用户输入直接连接到SQL中,则可以以不安全的方式使用WebMatrix。 Mark工作的结果是一个单独的数据访问框架,它类似于Rob的不依赖于WebMatrix.data。

simple.data与massive和webmatrix.data的动态类型一起工作。它可能会对从PHP迁移到ASP.NET的人更呼吁,因为它们可能更熟悉主动记录模式以及它的工作原理。没有选项来返回SQL。 Simple.Data支持不断增长的数据库范围,而不仅仅是SQL Server和SQL CE,并且作为轻量级数据访问框架,它持有相当多的承诺。我觉得它不太可能向那些了解数据库和SQL的人不太可能吸引人。

simple.data需要一个连接字符串。同样,这可以在Web.config中定义,但必须具有特定名称(至少,此刻):

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="真的" targetFramework="4.0"/>
  </system.web>
  <connectionStrings>
    <add name="simple.data..Properties.Settings.DefaultConnectionString" 
         connectionString="Data Source=<full path to db>\Northwind.sdf;" 
         providerName="System.Data.SqlServerCe.4.0"/>
  </connectionStrings>
</configuration>

或者,您可以在OpenFile方法中提供连接字符串:

@using SD = Simple.Data;
@{
    var db = SD.Database.OpenFile(Server.MapPath("~/App_Data/Northwind.sdf"));
}

如果您使用的是webmatrix,则默认引用webmatrix.data。这在简单的问题中引入了一些问题.data还定义了一个数据库类。因此,对数据库类的任何引用都将含糊不清。解决此问题的最简单方法是使用别名的引用简单。我用SD作为我的别名进行简单.data。您当然可以只是使用完全限定的命名空间: simple.data.database.openfile() 但这可能会变得无聊,以便在一段时间内输入。除此之外,不需要配置(类定义文件)。

数据库类具有所有方法,就像大规模一样,但它也有各种各样的查找方法:FindAll,FindBy,FindAllby。其中的最后一个允许您将充当筛选器的文件名附加,并通过该值。这就像这个简单的.data有助于避免任何SQL注入问题。以下是使用4个包含4的所有产品的一种方法:

@{
    var db = SD.Database.OpenFile(Server.MapPath("~/App_Data/Northwind.sdf"));
    var products = db.Products.FindAllByCategoryID(4);
}
@foreach(var product in products){
    @Product.ProductName.<br />
}

Simple.data还具有许多其他命令,用于插入,删除和更新数据。它还能够遍历由外键定义的关系。获得每个类别中的产品数量并不像SQL一样清晰切割,我发现我可以弄清楚如何做到这一点不符合性能:

@{
    var categories = new List<string>();
    products = db.Products.All();
    foreach(var product in products){
        foreach (var category in product.Categories){
           categories.Add(category.CategoryName);
        }
    }
    var result = categories.GroupBy(c => c).Select(g => new { Category = g.Key, Count = g.Count() });

    foreach(var item in result){
        @:@item.Category (@item.Count)<br />
    }
}

我希望我有这个糟糕的错误,因为可以检索来自产品表中的所有产品,然后在循环中检索与产品的类别相关联的类名,这意味着每个产品。所有类别名称都已加载在列表中,然后对某些LINQ进行,以获取De-PagePliced类别名称以及每个LINPOPLED类别名称。

你应该用哪个?如果您刚刚开始,我强烈建议您使用标准的WebMatrix.data库。 WebMatrix.data.stronglytyty肯定有一个地方,如果您想向对象构建应用程序。巨大是一个很好的少量实用程序,但似乎是作者在整个C#动态的事情周围的一个实验。看到它是否有趣,看它是如何发展的。最后,Simple.data承诺很多,但还没有准备好黄酮时间。根据Mark Rendle的博客,Simple.data似乎已经开始作为概念证明,并且可能并非旨在与它一样生长。大量的工作已经进入了简单的.data,它会再次有趣,看看这是否进一步开发并以何种方式开发。

提供包含每个库的样本的下载,包括WebMatrix.data 这里