各位好!
本人最近在学习Access数据库。在尝试使用C#语言在WPF项目内进行Access数据库的连接与记录修改。
网上有很多文章将此方面内容,但都是OleDbCommandBuilder和OleDbDataAdapter联合使用,好处很多,但弊端显而易见:一旦查询为基于多表的联合查询,若要修改记录,OleDbCommandBuilder便不可使用。
直接使用OleDbCommand进行操作,本人已经摸索明白。但如何在不使用OleDbCommandBuilder情况下使用OleDbDataAdapter更新Access数据库记录,本人才疏学浅,实在是搞不懂,还请指点。
本人的需求很简单:
1、单独使用OleDbDataAdapter类(不使用OleDbCommandBuilder)
2、使用OleDbDataAdapter类的Update方法,更新所有在datagrid控件内修改了公司名称的数据库记录。(改什么公司名称随意)
Access数据库结构(已去除敏感信息)
该查询实例的Jet-SQL语句:
SELECT T0101_公司情况表.公司名称_PK, T0101_公司情况表.统一社会信用代码, T0301_fdc证件信息表.证件编号 FROM T0101_公司情况表 INNER JOIN T0301_fdc证件信息表 ON T0101_公司情况表.公司名称_PK = T0301_fdc证件信息表.公司名称_FK;
WPF项目前端Xaml代码
1 <Window x:Class="WpfAccess_2.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:WpfAccess_2" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="657.812" Width="1276.562"> 9 <Grid> 10 <DataGrid x:Name="dataGrid" Margin="10,198,10,10" AutoGenerateColumns="True"/> 11 <Button x:Name="btn_Read" Content="读取" HorizontalAlignment="Left" VerticalAlignment="Top" Width="212" Margin="10,10,0,0" Height="66" FontSize="20" Click="Btn_Read_Click"/> 12 <Button x:Name="btn_Update" Content="直接更新
Update" HorizontalAlignment="Left" Margin="227,10,0,0" VerticalAlignment="Top" Width="212" Height="66" FontSize="20" Click="Btn_Update_Click"/> 13 <Button x:Name="btn_Clear" Content="清除" HorizontalAlignment="Left" Margin="10,81,0,0" VerticalAlignment="Top" Width="212" Height="66" Click="Btn_Clear_Click" FontSize="20"/> 14 <Button x:Name="btn_Update2" Content="使用
OleDbDataAdapter
更新(Update2)" HorizontalAlignment="Left" Margin="227,81,0,0" VerticalAlignment="Top" Width="212" Height="82" Click="Btn_Update2" FontSize="20"/> 15 16 </Grid> 17 </Window>
WPF项目后端C#代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Windows; 7 using System.Windows.Controls; 8 using System.Windows.Data; 9 using System.Windows.Documents; 10 using System.Windows.Input; 11 using System.Windows.Media; 12 using System.Windows.Media.Imaging; 13 using System.Windows.Navigation; 14 using System.Windows.Shapes; 15 using System.Data.OleDb; 16 using System.Data; 17 18 namespace WpfAccess_2 19 { 20 /// <summary> 21 /// MainWindow.xaml 的交互逻辑 22 /// </summary> 23 public partial class MainWindow : Window 24 { 25 public MainWindow() 26 { 27 InitializeComponent(); 28 InitializeMyComponent(); 29 } 30 31 OleDbConnection connection; 32 OleDbDataAdapter dataAdapter; 33 DataTable dataTable; 34 private void InitializeMyComponent() 35 { 36 connection = new OleDbConnection() 37 { 38 ConnectionString = Properties.Settings.Default.myConnectString 39 //myConnectString为存放的连接字符串 40 }; 41 string selectCommand = "SELECT T0101_公司情况表.公司名称_PK, T0101_公司情况表.统一社会信用代码, T0301_fdc证件信息表.证件编号 FROM T0101_公司情况表 INNER JOIN T0301_fdc证件信息表 ON T0101_公司情况表.公司名称_PK = T0301_fdc证件信息表.公司名称_FK"; 42 dataAdapter = new OleDbDataAdapter(selectCommand, connection); 43 dataTable = new DataTable(); 44 } 45 46 47 private void Btn_Read_Click(object sender, RoutedEventArgs e) 48 { 49 dataTable.Clear(); 50 dataAdapter.Fill(dataTable); 51 dataGrid.ItemsSource = dataTable.DefaultView;//这句话好像只能放这里,否则datagrid控件内显示不正常。 52 } 53 54 private void Btn_Update_Click(object sender, RoutedEventArgs e) 55 { 56 //使用OleDbCommand直接操作数据库。 57 //OleDbCommandBuilder()只能针对单个表用,使用有限制。 58 OleDbCommand oleDbCommand = new OleDbCommand() 59 { 60 CommandText = "UPDATE T0101_公司情况表 SET 公司名称_PK = @查询参数1 WHERE 统一社会信用代码 = '91420300063507079P'",//使用特定“统一社会信用代码”定位被修改的记录,目前只会这种方式 61 Connection=connection, 62 }; 63 OleDbParameter parameter = new OleDbParameter("@查询参数1", OleDbType.VarChar, 50, "公司名称_PK"); 64 Random random = new Random(2); 65 parameter.Value = "测试公司名称" + random.Next(1, 999);//让名字每次不一样 66 oleDbCommand.Parameters.Add(parameter); 67 68 connection.Open(); 69 oleDbCommand.ExecuteNonQuery(); 70 connection.Close(); 71 72 dataTable.Clear(); 73 dataAdapter.Fill(dataTable); 74 } 75 76 private void Btn_Clear_Click(object sender, RoutedEventArgs e) 77 { 78 dataTable.Clear(); 79 } 80 81 private void Btn_Update2(object sender, RoutedEventArgs e) 82 { 83 //直接使用OleDbDataAdapter的Update方法,求教各位专家 84 } 85 } 86 }
试试构造一个command实例赋值给OleDbDataAdapter的UpdateCommand属性
dataAdapter.UpdateCommand = command;
https://docs.microsoft.com/en-us/dotnet/api/system.data.oledb.oledbdataadapter.updatecommand?view=netframework-4.8
你好!
这个MSDN的例子我看过,但是本人功底不够,实在是看不懂,你可否针对我的实际需求,具体说明下?
此例子的中文链接:
https://docs.microsoft.com/zh-cn/dotnet/api/system.data.oledb.oledbdataadapter.updatecommand?view=netframework-4.8
我写了如下语句,运行后没有任何反应。
1 private void Btn_Update2(object sender, RoutedEventArgs e) 2 { 3 //使用OleDbDataAdapter的Update方法 4 OleDbCommand updateCommand = new OleDbCommand() 5 { 6 CommandText = "UPDATE T0101_公司情况表 SET 公司名称_PK = ? WHERE 统一社会信用代码 = '91420300063507079P'", 7 Connection = connection 8 }; 9 updateCommand.Parameters.Add("公司名称_PK", OleDbType.VarChar, 255, "公司名称_PK").Value = "公司名称345"; 10 dataAdapter.UpdateCommand = updateCommand; 11 dataAdapter.Update(dataTable); 12 }
@syzcyyx:
仔细看了下MSDN文档。UpdateCommand的作用是“在 OleDbCommand 期间用于在对应于 Update(DataSet) 中的修改行的数据源中更新记录的 DataSet。”
所以绕不过去OleDbCommandBuilder 。我机器上也没有access,这段代码应该在MSSQL Server版本下可以运行。
private static void update_ds(string constr)
{
using (OleDbConnection conn = new OleDbConnection(constr))
{
conn.Open();
DataSet ds = new DataSet();
string sql = "select * from Students_demo; ";
OleDbDataAdapter adapate = new OleDbDataAdapter(sql, conn);
adapate.Fill(ds, "table1");
foreach (DataRow datarow in ds.Tables[0].Rows)
{
//更新Chn字段为'99',//20->99
datarow["Chn"] = "99";
}
OleDbCommandBuilder builder = new OleDbCommandBuilder(adapate);
adapate.Update(ds, "table1");
}
}
@邀月:
你好,我之所以提出不用OleDbCommandBuilder类的需求,是因为OleDbCommandBuilder类对于基于多表的联合查询无能为力,而在关系型数据库中,这种情况几乎无法避免。
对多表联合查询使用OleDbCommandBuilder,会有下面的报错: