前面说了数据提供程序建立在6个抽象基类之上,特定的数据库继承了这些基类。
所以利用抽象基类以及对应的抽象接口,我们就能够构建灵活的代码库。
如果现在做一个针对sel server的应用程序,下一次转向其他数据库平台。就不像特定数据库的数据提供程序那样硬编码,无需重新修改,编译程序。
在抽象基类以及接口上,ADO.NET还提供了一个叫DbProviderFactorys的类,这个类也叫做数据提供工厂模型。
工厂模型就是对抽象基类和接口的再包装,通过静态方法.GetFactory,并指定包含数据提供程序的.NET命名空间名称,就能获取相关的对象(比如连接,命令,数据读取器等)。
//工厂模型
DbProviderFactory df = DbDbProviderFactorys.GetFactory("System.Data.SqlClient");
using(DbConnection cn = df.CreateConnection())
{
cn.ConnectionString= "连接字符串";
cn.Open();
DbCommand cmd=df.CreateCommand();
cmd.Conection=cn;
cmd.CommandText="Select*From 表格名";
using(DbDataReader dr=cmd.ExecuteReader())
{
while(dr.Read())
}
}
但是数据工厂模型也有缺点,代码只能通过抽象类的成员来使用所有提供程序通用的方法。
使得我们不能直接访问特定DBMS的漂亮功能。
并且这种模型需要一直保持对数据库的连接,任何操作都会被直接更新在数据库上。
于是在这个基础上,ADO.NET提出了新的连接模型,即断开式连接。
断开式连接模型无需一直保持对数据库的连接,它操作的仅仅是从数据库中读取在内存中的副本,优点在于能随时对内存内容进行更改,
只要不提交到物理数据库,就不会破坏物理数据库的内容。
因为操作内存中的副本,所以可以同时具备多个副本,让操作回滚成为可能。
连接到服务器,注意服务器的名字不要填错。
事实上该步骤完全没必要,只是对连接数据库的模拟。
vs2017自带数据库LocalDB默认就是连接好的。
打开对象资源管理器,默认就是连接好的。
只需要把连接字符串复制出来即可。
namespace ConsoleApp1
{
public class Program
{
static void Main()
{
//连接字符串和sql命令
string connstr = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=我的web通信数据库;Integrated Security=True;";
string sql = "select * from dbo.Table";
//创建一个表用来接收数据
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(connstr, sql);
//用适配器的fill方法把数据从数据库中取出,填充到创建的表dt里
da.Fill(dt);
//也可以创建一个结果集,dbo是结果集的名字,随意取
// DataSet ds = new DataSet("dbo");
//把dbo.Table表填充进结果集
// da.Fill(ds, "dbo.Table");
Console.ReadKey();
}
}
不过一运行就报错在SqlDataAdapter行,从索引 0 处开始,初始化字符串的格式不符合规范。
反复检查,连接字符串没错啊,sql语句好像也没错啊?
蠢死啦,把SqlDataAdapter da = new SqlDataAdapter(connstr, sql)的参数写反了,应该是SqlDataAdapter da = new SqlDataAdapter(sql,connstr);
但是运行到 da.Fill(dt)有出错了,报告Incorrect syntax near the keyword 'Table‘
查询资料,好像说Table是T-SQL的关键字。
而且无论用的小写还是大写,最后结果都会被转换成大写,因此Table不能用,table也不能用。
修改名字试试,把dbo.Table改成dbo.tab
好像无论怎么修改,名字都是默认dbo开头,有点烦躁。
终于终于,折腾了一下午成功了~~~
补充:9月12号,再试试sql server localdb 的EF框架:
①建立edmx文件
②撸代码,发现网上不少资料已经过时了,怎么写都不对,还是去msdn看了官方文档才知道怎么写。
可能是EF6.X的版本跟以前有了细致区别?
using System.Windows;
//添加using指令 System.Data.Entity 将 Load 扩展方法引入作用域
using System.Data.Entity;
namespace Wpfsqlserverdemo
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
//对象上下文类
testEntities context = new testEntities();
private void data(object sender, RoutedEventArgs e)
{
{
// This method enumerates the results of the query,
// similar to ToList but without creating a list.
context.cars.Load();
//数据绑定写法不同,必须先load
dataGrid.ItemsSource = context.cars.Local;
}
}
private void click_label(object sender, RoutedEventArgs e)
{
context.cars.Add(new car() { 厂商 = "徐工", 车名 = "挖掘机" });
context.SaveChanges();
}
}
}