使用 ADO.NET 数据服务在 Silverlight 中执行 CRUD 操作






4.77/5 (11投票s)
使用 ADO.NET 数据服务(Astoria)在 Silverlight 中执行 CRUD(创建、检索、更新、删除)操作的最简单方法。
引言
本文介绍了使用 ADO.NET 数据服务(Astoria)在 Silverlight 中执行 CRUD(创建、检索、更新、删除)操作的最简单方法。在 Silverlight 中与数据库通信有两种方式
- Web服务
- ADO.NET 数据服务
我选择 ADO.NET 数据服务用于本文,因为 RESTful 服务和 RIA(富互联网应用程序)开发是最佳匹配。如果您不了解 ADO.NET,请阅读我的上一篇文章 这里。
目录
- 必备组件
- 在 SQL 2005 中创建数据库
- 在 Visual Studio 2008 中创建 ADO.NET 数据服务
- 为 Silverlight 项目创建 Astoria 代理
- 在 Silverlight 中插入新记录
- 在 Silverlight 中更新现有记录
- 在 Silverlight 中从数据库检索记录
- 在 Silverlight 中删除记录
- 结论
- 常见问题解答
必备组件
- Visual Studio 2008
- Microsoft SQL Server 2005 Express Edition with Advanced Services 或 SQL Express 和 Management Studio
- ADO.NET 数据服务 Silverlight 附加组件
- ASP.NET 3.5 扩展预览版(2007 年 12 月)
- Silverlight 1.1 九月更新
- ADO.NET Entity Framework Beta 3
- XML 编辑器 QFE
- ADO.NET Entity Framework Tools 2007 年 12 月社区技术预览版
在 SQL 2005 中创建数据库
注意:如果您已经知道如何在 SQL 2005 中创建数据库,请跳过并跳转到下一节。
步骤 1:打开 SQL Server Management Studio Express
步骤 2:连接到您已安装在本地计算机上的 SQL Server
步骤 3:在对象资源管理器中右键单击“数据库”节点,然后选择“新建数据库”
步骤 4:输入您的数据库名称(在此示例中我将其命名为“MyStore”)然后单击“确定”按钮
步骤 5:右键单击您创建的数据库的“表”节点,然后选择“新建表”
步骤 5:创建名为“ProductID(INT Identity PK)”和“ProductName”的两个列。将表命名为“Products”
好的。以上就是关于在 SQL 2005 中创建新表的内容。
在 Visual Studio 2008 中创建 ADO.NET 数据服务
注意:我在之前的文章“从 Silverlight 使用 ADO.NET 数据服务(Astoria)”中已经解释了如何创建 ADO.NET 数据服务。(在此示例中我将使用 ASP.NET 3.5 扩展 Web 应用程序)。如果您已经阅读过这篇文章,请跳过本节。
步骤 1:创建新的 ASP.NET 3.5 扩展 Web 应用程序
- 单击“新建项目”图标或按“Ctrl+Shift+N”。
- 选择“ASP.NET Web 应用程序”并将应用程序命名为“CRUDSilverlight”。
- 单击“确定”按钮。
步骤 2:创建“ADO.NET Entity Data Model”
创建新的 ASP.NET 3.5 扩展项目后,您需要将“ADO.NET Entity Data Model”添加到您的项目中。您需要从 SQL 2005 中创建的表中生成数据模型。如果您想查看添加 ADO.NET Entity Data Model 的所有截图,请在这篇文章中查看“创建 ADO.NET Entity Data Model”。
步骤 3:创建“ADO.NET 数据服务”
添加 ADO.NET Entity Data Model 后,您需要将“ADO.NET 数据服务”添加到您的项目中。然后,您需要在第一行放置数据源类名,并取消注释 InitializeService()
函数中的“config.SetResourceContainerAccessRule("MyEntityset", ResourceContainerRights.AllRead);
”。将“MyEntityset”替换为“*”,并将“AllRead”更改为“All”。
public class WebDataService1 : WebDataService<MyStoreModel.MyStoreEntities>
{
// This method is called once during service initialization to allow
// service-specific policies to be set
public static void InitializeService(IWebDataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are
// visible, updatable, etc.
// (for testing purposes use "*" to indicate all entity sets/service
// operations, but that option should NOT be used in production systems)
// Example for entity sets (this example uses
// "AllRead" which allows reads but not writes)
config.SetResourceContainerAccessRule("*", ResourceContainerRights.All);
// Example for service operations
//config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}
// Query interceptors, change interceptors and service operations go here
}
步骤 4:将自动分配的端口更改为您 Web 应用程序的特定端口
请注意,此步骤非常重要。我们应该使用静态端口以防止跨域问题。Web 选项卡位于项目的属性窗口下。
为 Silverlight 项目创建 Astoria 代理
当我撰写关于“如何在 Silverlight 中使用 ADO.NET 数据服务”时,我没有使用 Webdatagen.exe 为 Astoria 生成代理类。Bryant 在这篇文章中指出了生成代理类的方法。(非常感谢 Bryant)因此,我们可以节省在 Silverlight 项目和 ASP.NET Web 项目之间复制代码的时间。
- 转到“Visual Studio 2008 命令提示符”。(注意:如果您使用的是 Windows Vista,则必须以管理员权限运行命令行。右键单击菜单并选择“以管理员身份运行”。否则,Webdatagen.exe 将无法在磁盘上写入生成的文件。)
- 转到“C:\Program Files\Microsoft ASP.NET 3.5 Extensions>”文件夹。
- 在命令行中输入以下命令
"WebDataGen.exe /mode:ClientClassGeneration
/outobjectlayer:Products.cs
/uri:https://:52799/WebDataService1.svc"
Products.cs 是我们要生成的代理文件的名称。https://:52799/WebDataService1.svc 是 ADO.NET 数据服务的 URL。
现在,检查 Microsoft ASP.NET 3.5 Extensions 下的 Products.cs。您可以将此代理文件添加到 Silverlight 项目中。
好的。我们已经完成了使用 ADO.NET 数据服务在 Silverlight 中执行 CRUD 操作的准备工作。让我们看看如何执行这些操作。
在 Silverlight 中插入新记录
您可以创建一个 Products
对象的实例,并根据需要设置产品名称。由于产品 ID 是标识字段,因此我们无需指定。由于我们要添加数据,因此会将 MergeOption
设置为 AppendOnly
。
try{
MyStoreModel.Products _products = new MyStoreModel.Products();
_products.ProductName = "Windows Vista";
MyStoreModel.MyStoreEntities _mystore =
new MyStoreModel.MyStoreEntities(_serviceUriString);
_mystore.MergeOption = Microsoft.Data.WebClient.MergeOption.AppendOnly;
_mystore.AddObject("Products", _products);
_mystore.SaveChanges();
insertTextBlock.Text = "New record has been added successfully." +
" Please check Products table in SQL";
}
catch(Exception ex){
throw ex;
}
在 Silverlight 中更新现有记录
下面的代码用于更新数据库中的现有记录。我们将使用“OverwriteChanges
” MergeOption
进行更新。
try{
MyStoreModel.MyStoreEntities _mystore =
new MyStoreModel.MyStoreEntities(_serviceUriString);
_mystore.MergeOption =
Microsoft.Data.WebClient.MergeOption.OverwriteChanges;
MyStoreModel.Products _products = new MyStoreModel.Products();
_products.ProductID = 1;
_products.ProductName = "Visual Studio 2008 Professional";
_mystore.AttachObject("Products", _products);
_mystore.UpdateObject(_products);
updateTextBlock.Text = "ProductID(#1) has been updated successfully." +
" Please check Products table in SQL";
_mystore.SaveChanges();
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
注意:Astoria 的 ReadMe.txt 中写道:
更新(调用
UpdateObject
后跟SaveChanges
方法)即使操作在服务器端成功,也可能返回异常。
所以,您在更新记录时会遇到异常,但不用担心。即使出现异常,您的记录也会在 SQL 数据库中更新。这是一个已知问题,将在下一个版本中修复。
在 Silverlight 中从数据库检索记录
以下代码用于从数据库检索记录。您还可以参考我博客上的文章:“使用 ADO.NET 数据服务”。
try {
MyStoreModel.MyStoreEntities _mystore =
new MyStoreModel.MyStoreEntities(_serviceUriString);
_mystore.MergeOption = Microsoft.Data.WebClient.MergeOption.OverwriteChanges;
Microsoft.Data.WebClient.WebDataQuery<MyStoreModel.Products>
products = _mystore.CreateQuery<MyStoreModel.Products>(
"/Products?$orderby=ProductID");
double top=0;
foreach (MyStoreModel.Products p in products) {
TextBlock tbk = new TextBlock();
tbk.Text = p.ProductName;
tbk.Height = 50;
top += tbk.Height;
tbk.SetValue(TopProperty, top);
view.Children.Add(tbk);
}
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
在 Silverlight 中删除记录
try{
MyStoreModel.MyStoreEntities _mystore =
new MyStoreModel.MyStoreEntities(_serviceUriString);
_mystore.MergeOption = Microsoft.Data.WebClient.MergeOption.OverwriteChanges;
MyStoreModel.Products _products =
new MyStoreModel.Products();
_products.ProductID = 1;
_mystore.AttachObject("Products", _products);
_mystore.DeleteObject(_products);
_mystore.SaveChanges();
deleteTextBlock.Text = "ProductID(#1) has been deleted " +
"successfully. Please check Products table in SQL";
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
将配置存储在 XML 中
由于 Silverlight 项目中没有设置或 web.config,我选择使用 XML 文件存储配置信息。但我认为在实际项目中将扩展名更改为 config 会更好。在此示例中,我将服务 URI 存储在 Configs.xml 文件中。
<?xml version="1.0" encoding="utf-8" ?>
<ServiceUriString>https://:52799/WebDataService1.svc</ServiceUriString>
由于我不想使用 WebRequest
加载此 XML,因此我将其嵌入到项目中。以下代码用于在 Silverlight 中读取 XML 文件
Stream stream = this.GetType().Assembly.GetManifestResourceStream(
"SilverlightProject1.Configs.xml");
XmlReader reader = XmlReader.Create(stream);
while (reader.Read()) {
if (reader.IsStartElement()) {
if ("ServiceUriString" == reader.LocalName) {
reader.Read();
string _serviceURL = reader.Value;
reader = null;
stream.Dispose();
return _serviceURL;
}
}
}
reader = null;
stream.Dispose();
return string.Empty;
结论
这就是在 Silverlight 中执行 CRUD 操作的所有内容。抱歉,我的示例中没有漂亮的 UI。由于本文专注于 CRUD 操作,因此我不想在示例中添加复杂的 UI 代码。希望您觉得有用,如果您有任何意见或建议,请随时告诉我。谢谢。
常见问题解答
- 我在从数据库检索记录时遇到了这个异常“根级别的 DTD 出现无效字符。行 1,位置 1”。为什么?
- 我在更新记录时遇到这个异常“由于对象的当前状态,操作无效”。为什么?
- “无法更新 EntitySet 'Products',因为它具有 DefiningQuery 且在 <ModificationFunctionMapping> 元素中不存在支持当前操作的 <InsertFunction> 元素”
- 我正在尝试使用 WebDataGen.exe 生成代理类,但即使命令行中没有显示错误,也没有生成任何文件。
- 您将服务 URL 存储在 Silverlight 项目的哪里?
- 我还有其他未包含在 FAQ 中的问题。如何联系您?
数据服务的 UriString
错误。请检查您是否有任何拼写错误。另外,UriString
是区分大小写的。
正如我在“更新记录”部分所写,这是一个已知问题,将在下一个版本中修复。您的记录将在数据库中更新,但您会遇到异常。只需忽略该异常。
只需删除项目中的 Entity Model,然后重新创建新的。我在创建此示例时遇到了这个问题。我所做的是,我在 VS 中创建了 Entity Model,而没有在 Products 表中创建主键。当我尝试插入新记录时,我收到了这个错误。因此,我删除了 Entity Model 并重新创建了它。这将解决问题。我认为还有其他更好的方法可以做到这一点,但我不知道。如果有人能告诉我方法,那就太好了。
如果您是 Windows Vista 用户,则启动命令行时需要以管理员身份运行。
由于没有设置或 web.config,我将连接字符串存储在 Configs.xml 中,该文件在 Silverlight 中设置为“嵌入的资源”。有一个名为“Configs.cs”的类,它将从该 XML 文件读取服务 URL 字符串。
如果您有任何问题或建议,可以在这篇博文中发表评论。我总是阅读所有评论,并会尽快回复。