Appearance
C# 开发笔记
WinForm
控件命名规范

ADO.NET
连接数据库 Connection 对象
csharp
string constr = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.20.1)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=abac)));User ID=abac;Password=abac";
OracleConnection con = new OracleConnection(constr);//连接到数据库
this.con.Open();ConnectionState 枚举

关闭连接
Dispose 和 Close
Close用于关闭一个连接,而Dispose方法不仅关闭一个连接,而且还清理连接所占用的资源。当调用Close 方法关闭连接后,还可以再调用Open方法打开连接,而如果使用Dispose方法关闭连接,就不能再调用Open 方法打开连接,必须重新初始化连接再打开。
执行SQL语句 Command对象
ExecuteNonQuery()方法,返回受影响的行数
csharp
OracleCommand command = new OracleCommand("insert into " +
"ABXRTEST02(SYSID,STRING1,NUMBER1,DT1) values ('" +
sysid_textbox.Text + "','" + string1_textbox.Text +
"','" + number1_textbox.Text + "',to_date('" +
dt1_date.Text + "','yyyy-mm-dd'))", this.con);
command.ExecuteNonQuery();ExecuteReader()方法,返回一个SqlDataReader对象
ExecuteScalar()方法,返回结果集中的第一行第一列(若结果集为空返回空引用)
读取数据 DataReader对象
HasRows()方法,返回是否有一行或多行数据
Read()方法,返回是否存在多个行
数据适配器 DataAdapter对象
查询数据并填充至DataTable
csharp
string strQuery = @"select SYSID,STRING1,NUMBER1,DT1 from ABXRTEST02 where SYSID='" + SYSID +
"' and STRING1='" + STRING1 + "' and NUMBER1='" + NUMBER1 + "'";
OracleDataAdapter adapter = new OracleDataAdapter(strQuery, this.con);
DataTable dtResult = new DataTable();
adapter.Fill(dtResult);
adapter.Dispose();DataSet对象
相当于存放于内存的小型数据库,可以包含数据表、数据列、数据行、视图、约束关系等信息
合并DataSet内容
Merge(DataSet ds, bool Pc, MissingSchemaAction msa)方法
ds:被合并的数据和架构
pc:要保留当前DataSet中的更改则为true,否则为false
msa:MissingSchemaAction枚举值之一

复制DataSet内容
Copy()方法,返回一个DataSet的副本
FreeSQL
数据库连接单例
csharp
using System;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace Demo_7_4 {
public class DB {
static Lazy<IFreeSql> oracleLazy = new Lazy<IFreeSql>(() => new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.Oracle, "user id=abac;password=abac;data source=//10.168.8.1:1521/oradbsgl;Pooling=true;Max Pool Size=2")
.UseAutoSyncStructure(true)
.UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper)
.UseNoneCommandParameter(true)
.UseMonitorCommand(cmd => Trace.WriteLine(cmd.CommandText))
.Build());
public static IFreeSql oracle => oracleLazy.Value;
}
}增
csharp
fsql.Insert(new ABXRTEST02 {
STRING1 = txtString1.Text,
NUMBER1 = int.Parse(txtNumber1.Text),
DT1 = dtpickerDt1.Value
}).ExecuteAffrows();删
csharp
fsql.Delete<ABXRTEST02>()
.Where(b => b.SYSID == this.curIdx)
.ExecuteAffrows();改
csharp
fsql.Update<ABXRTEST02>()
.Set(b => b.STRING1, txtString1.Text)
.Set(b => b.NUMBER1, int.Parse(txtNumber1.Text))
.Set(b => b.DT1, dtpickerDt1.Value)
.Where(b => b.SYSID == this.SYSID)
.ExecuteAffrows();查
csharp
fsql.Select<ABXRTEST02>()
.Where(a => a.SYSID == this.SYSID)
.ToList();csharp
fsql.Select<ABXRTEST02>().ToList();LINQ
实操
C#连接Oracle
数据表结构
首先是数据表结构如下

WinForm界面
界面如下

界面注意点:
DT1 对应的 DateTimePicker 的 Format 属性改为 Short
STRING1 的数据列为nvarchar2(20),故其对应TextBox应设置最大长度(MaxLength)为20
SYSID和NUMBER1对应的TextBox应只能输入数字,故为其KeyPress事件添加方法如下
c#
private void number1_textbox_KeyPress(object sender, KeyPressEventArgs e) {
if (!(Char.IsNumber(e.KeyChar)) && e.KeyChar != (char)8) { e.Handled = true; }
}主要代码
数据库连接代码
csharp
OracleConnection con;
string constr = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=10.168.8.109)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=abac)));User ID=abac;Password=abac";
private void Form1_Load(object sender, EventArgs e) {
this.con = new OracleConnection(constr);//连接到数据库
this.con.Open();
}获取数据列表
csharp
private void getList() {
string cmdText = @"select SYSID,STRING1,NUMBER1,DT1 from ABXRTEST02 ";
OracleDataAdapter adapter = new OracleDataAdapter(cmdText, constr);
DataSet dataSet = new DataSet();
adapter.Fill(dataSet, "QueryResult");
adapter.Dispose();
DataTable dt = dataSet.Tables[0];
this.dataGridView1.Columns["SYSID"].DataPropertyName = "SYSID";
this.dataGridView1.Columns["STRING1"].DataPropertyName = "STRING1";
this.dataGridView1.Columns["NUMBER1"].DataPropertyName = "NUMBER1";
this.dataGridView1.Columns["DT1"].DataPropertyName = "DT1";
this.dataGridView1.DataSource = dt;
}添加数据时要注意,SYSID不能重复
csharp
try {
OracleCommand command = new OracleCommand("insert into " +
"ABXRTEST02(SYSID,STRING1,NUMBER1,DT1) values ('" +
sysid_textbox.Text + "','" + string1_textbox.Text +
"','" + number1_textbox.Text + "',to_date('" +
dt1_date.Text + "','yyyy-mm-dd'))", this.con);
command.ExecuteNonQuery();
command.Dispose();
MessageBox.Show("添加成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
} catch (Exception ex) {
MessageBox.Show("添加失败,SYSID重复!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}全部代码
Form1.cs
csharp
using System.Data;
using System.Drawing;
using Oracle.ManagedDataAccess.Client;//oracle数据提供程序
namespace Demo_7_4 {
public partial class Form1 : Form {
OracleConnection con;
string constr = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=10.168.6.29)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=abac)));User ID=abac;Password=abac";
string flag = "";
public Form1() {
InitializeComponent();
}
/// <summary>
/// 添加
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e) {
this.sysid_textbox.Text = "";
this.string1_textbox.Text = "";
this.number1_textbox.Text = "";
this.dt1_date.Text = "";
this.sysid_textbox.Enabled = true;
this.string1_textbox.Enabled = true;
this.number1_textbox.Enabled = true;
this.dt1_date.Enabled = true;
this.button3.Enabled = false;
this.button2.Enabled = false;
this.add_button.Enabled = false;
this.button1.Enabled = true;
this.flag = "add";
}
/// <summary>
/// 修改
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e) {
this.sysid_textbox.Enabled = false;
this.string1_textbox.Enabled = true;
this.number1_textbox.Enabled = true;
this.dt1_date.Enabled = true;
this.button1.Enabled = true;
this.button3.Enabled = false;
this.button2.Enabled = false;
this.add_button.Enabled = true;
this.flag = "edit";
}
/// <summary>
/// 删除
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e) {
if ((MessageBox.Show("是否真的要删除用户" + this.sysid_textbox.Text + "吗?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question)).Equals(DialogResult.Yes)) {
String strQuery = "delete from ABXRTEST02 where SYSID='" + sysid_textbox.Text + "'";
OracleCommand command = new OracleCommand(strQuery, this.con);
int num = command.ExecuteNonQuery();
command.Dispose();
MessageBox.Show("删除成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
getList();
this.sysid_textbox.Text = "";
this.string1_textbox.Text = "";
this.number1_textbox.Text = "";
this.dt1_date.Text = "";
this.sysid_textbox.Enabled = false;
this.string1_textbox.Enabled = false;
this.number1_textbox.Enabled = false;
this.button3.Enabled = false;
this.button2.Enabled = false;
this.button1.Enabled = false;
this.dt1_date.Enabled = false;
}
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) {
DataTable dt = (DataTable)this.dataGridView1.DataSource;
if (e.RowIndex > -1) {
string SYSID = dt.Rows[e.RowIndex]["SYSID"].ToString();
string STRING1 = dt.Rows[e.RowIndex]["STRING1"].ToString();
string NUMBER1 = dt.Rows[e.RowIndex]["NUMBER1"].ToString();
string DT1 = dt.Rows[e.RowIndex]["DT1"].ToString();
string strQuery = @"select SYSID,STRING1,NUMBER1,DT1 from ABXRTEST02
where SYSID='" + SYSID + "' and STRING1='" + STRING1 + "' and NUMBER1='" + NUMBER1 +
"'";
OracleDataAdapter adapter = new OracleDataAdapter(strQuery, this.constr);
DataSet dataSet = new DataSet();
adapter.Fill(dataSet, "QueryResult");
adapter.Dispose();
DataTable dtResult = dataSet.Tables[0];
this.sysid_textbox.Text = dtResult.Rows[0]["SYSID"].ToString();
this.string1_textbox.Text = dtResult.Rows[0]["STRING1"].ToString();
this.number1_textbox.Text = dtResult.Rows[0]["NUMBER1"].ToString();
this.dt1_date.Text = dtResult.Rows[0]["DT1"].ToString();
this.button2.Enabled = true;
this.button1.Enabled = false;
this.add_button.Enabled = true;
this.button3.Enabled = true;
}
}
private void Form1_Load(object sender, EventArgs e) {
this.sysid_textbox.Enabled = false;
this.string1_textbox.Enabled = false;
this.number1_textbox.Enabled = false;
this.button3.Enabled = false;
this.button2.Enabled = false;
this.button1.Enabled = false;
this.dt1_date.Enabled = false;
this.con = new OracleConnection(constr);//连接到数据库
this.con.Open();
getList();
}
private void getList() {
string cmdText = @"select SYSID,STRING1,NUMBER1,DT1 from ABXRTEST02 ";
OracleDataAdapter adapter = new OracleDataAdapter(cmdText, constr);
DataSet dataSet = new DataSet();
adapter.Fill(dataSet, "QueryResult");
adapter.Dispose();
DataTable dt = dataSet.Tables[0];
this.dataGridView1.Columns["SYSID"].DataPropertyName = "SYSID";
this.dataGridView1.Columns["STRING1"].DataPropertyName = "STRING1";
this.dataGridView1.Columns["NUMBER1"].DataPropertyName = "NUMBER1";
this.dataGridView1.Columns["DT1"].DataPropertyName = "DT1";
this.dataGridView1.DataSource = dt;
}
private void button1_Click_1(object sender, EventArgs e) {
if (this.string1_textbox.Text == "") {
MessageBox.Show("STRING1不允许为空!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
this.string1_textbox.Focus();
return;
} else if (this.number1_textbox.Text == "") {
MessageBox.Show("NUMBER1不允许为空!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
this.number1_textbox.Focus();
return;
} else if (this.dt1_date.Text == "") {
MessageBox.Show("DT1不允许为空!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
this.dt1_date.Focus();
return;
}
if (this.flag == "add") {
try {
OracleCommand command = new OracleCommand("insert into " +
"ABXRTEST02(SYSID,STRING1,NUMBER1,DT1) values ('" + sysid_textbox.Text +
"','" + string1_textbox.Text + "','"
+ number1_textbox.Text + "',to_date('"
+ dt1_date.Text + "','yyyy-mm-dd'))", this.con);
command.ExecuteNonQuery();
command.Dispose();
MessageBox.Show("添加成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
} catch (Exception ex) {
MessageBox.Show("添加失败,SYSID重复!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
} else if (this.flag == "edit") {
OracleCommand command = new OracleCommand("update ABXRTEST02 set " +
"STRING1='" + string1_textbox.Text + "', " +
"NUMBER1='" + number1_textbox.Text + "', " +
"DT1=to_date('" + dt1_date.Text + "','yyyy-mm-dd') where SYSID='" + sysid_textbox.Text + "'", this.con);
command.ExecuteNonQuery();
command.Dispose();
MessageBox.Show("修改成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
getList();
this.button1.Enabled = false;
this.add_button.Enabled = true;
this.sysid_textbox.Enabled = false;
this.string1_textbox.Enabled = false;
this.number1_textbox.Enabled = false;
this.dt1_date.Enabled = false;
this.sysid_textbox.Text = "";
this.string1_textbox.Text = "";
this.number1_textbox.Text = "";
this.dt1_date.Text = "";
}
private void number1_textbox_KeyPress(object sender, KeyPressEventArgs e) {
if (!(Char.IsNumber(e.KeyChar)) && e.KeyChar != (char)8) { e.Handled = true; }
}
~Form1() {
this.con.Close();
}
}
}Form1.Designer.cs
csharp
namespace Demo_7_4 {
partial class Form1 {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
components = new System.ComponentModel.Container();
bindingSource1 = new BindingSource(components);
label1 = new Label();
label2 = new Label();
label3 = new Label();
label4 = new Label();
dataGridView1 = new DataGridView();
SYSID = new DataGridViewTextBoxColumn();
STRING1 = new DataGridViewTextBoxColumn();
NUMBER1 = new DataGridViewTextBoxColumn();
DT1 = new DataGridViewTextBoxColumn();
add_button = new Button();
button2 = new Button();
sysid_textbox = new TextBox();
string1_textbox = new TextBox();
number1_textbox = new TextBox();
dt1_date = new DateTimePicker();
button3 = new Button();
button1 = new Button();
((System.ComponentModel.ISupportInitialize)bindingSource1).BeginInit();
((System.ComponentModel.ISupportInitialize)dataGridView1).BeginInit();
SuspendLayout();
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(25, 42);
label1.Name = "label1";
label1.Size = new Size(51, 20);
label1.TabIndex = 0;
label1.Text = "SYSID";
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(698, 42);
label2.Name = "label2";
label2.Size = new Size(38, 20);
label2.TabIndex = 1;
label2.Text = "DT1";
//
// label3
//
label3.AutoSize = true;
label3.Location = new Point(465, 42);
label3.Name = "label3";
label3.Size = new Size(83, 20);
label3.TabIndex = 2;
label3.Text = "NUMBER1";
//
// label4
//
label4.AutoSize = true;
label4.Location = new Point(230, 42);
label4.Name = "label4";
label4.Size = new Size(73, 20);
label4.TabIndex = 3;
label4.Text = "STRING1";
//
// dataGridView1
//
dataGridView1.AccessibleRole = AccessibleRole.MenuPopup;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView1.Columns.AddRange(new DataGridViewColumn[] { SYSID, STRING1, NUMBER1, DT1 });
dataGridView1.Location = new Point(25, 215);
dataGridView1.Name = "dataGridView1";
dataGridView1.ReadOnly = true;
dataGridView1.RowHeadersWidth = 51;
dataGridView1.RowTemplate.Height = 29;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.Size = new Size(910, 342);
dataGridView1.TabIndex = 4;
dataGridView1.CellContentClick += dataGridView1_CellContentClick;
//
// SYSID
//
SYSID.HeaderText = "SYSID";
SYSID.MinimumWidth = 6;
SYSID.Name = "SYSID";
SYSID.ReadOnly = true;
SYSID.Width = 125;
//
// STRING1
//
STRING1.HeaderText = "STRING1";
STRING1.MinimumWidth = 6;
STRING1.Name = "STRING1";
STRING1.ReadOnly = true;
STRING1.Width = 125;
//
// NUMBER1
//
NUMBER1.HeaderText = "NUMBER1";
NUMBER1.MinimumWidth = 6;
NUMBER1.Name = "NUMBER1";
NUMBER1.ReadOnly = true;
NUMBER1.Width = 125;
//
// DT1
//
DT1.HeaderText = "DT1";
DT1.MinimumWidth = 6;
DT1.Name = "DT1";
DT1.ReadOnly = true;
DT1.Width = 200;
//
// add_button
//
add_button.Location = new Point(178, 134);
add_button.Name = "add_button";
add_button.Size = new Size(125, 49);
add_button.TabIndex = 5;
add_button.Text = "添加";
add_button.UseVisualStyleBackColor = true;
add_button.Click += button1_Click;
//
// button2
//
button2.Location = new Point(369, 134);
button2.Name = "button2";
button2.Size = new Size(135, 49);
button2.TabIndex = 6;
button2.Text = "修改";
button2.UseVisualStyleBackColor = true;
button2.Click += button2_Click;
//
// sysid_textbox
//
sysid_textbox.Location = new Point(99, 39);
sysid_textbox.Name = "sysid_textbox";
sysid_textbox.Size = new Size(125, 27);
sysid_textbox.TabIndex = 7;
sysid_textbox.KeyPress += number1_textbox_KeyPress;
//
// string1_textbox
//
string1_textbox.Location = new Point(309, 39);
string1_textbox.MaxLength = 20;
string1_textbox.Name = "string1_textbox";
string1_textbox.Size = new Size(125, 27);
string1_textbox.TabIndex = 8;
//
// number1_textbox
//
number1_textbox.Location = new Point(554, 39);
number1_textbox.Name = "number1_textbox";
number1_textbox.Size = new Size(125, 27);
number1_textbox.TabIndex = 9;
number1_textbox.KeyPress += number1_textbox_KeyPress;
//
// dt1_date
//
dt1_date.Format = DateTimePickerFormat.Short;
dt1_date.Location = new Point(763, 37);
dt1_date.Name = "dt1_date";
dt1_date.Size = new Size(172, 27);
dt1_date.TabIndex = 11;
//
// button3
//
button3.Location = new Point(568, 134);
button3.Name = "button3";
button3.Size = new Size(135, 49);
button3.TabIndex = 12;
button3.Text = "删除";
button3.UseVisualStyleBackColor = true;
button3.Click += button3_Click;
//
// button1
//
button1.Location = new Point(763, 134);
button1.Name = "button1";
button1.Size = new Size(135, 49);
button1.TabIndex = 13;
button1.Text = "确定";
button1.UseVisualStyleBackColor = true;
button1.Click += button1_Click_1;
//
// Form1
//
AutoScaleDimensions = new SizeF(9F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(965, 569);
Controls.Add(button1);
Controls.Add(button3);
Controls.Add(dt1_date);
Controls.Add(number1_textbox);
Controls.Add(string1_textbox);
Controls.Add(sysid_textbox);
Controls.Add(button2);
Controls.Add(add_button);
Controls.Add(dataGridView1);
Controls.Add(label4);
Controls.Add(label3);
Controls.Add(label2);
Controls.Add(label1);
Name = "Form1";
Text = "Form1";
Load += Form1_Load;
((System.ComponentModel.ISupportInitialize)bindingSource1).EndInit();
((System.ComponentModel.ISupportInitialize)dataGridView1).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private BindingSource bindingSource1;
private Label label1;
private Label label2;
private Label label3;
private Label label4;
private DataGridView dataGridView1;
private Button add_button;
private Button button2;
private TextBox sysid_textbox;
private TextBox string1_textbox;
private TextBox number1_textbox;
private DateTimePicker dt1_date;
private Button button3;
private DataGridViewTextBoxColumn SYSID;
private DataGridViewTextBoxColumn STRING1;
private DataGridViewTextBoxColumn NUMBER1;
private DataGridViewTextBoxColumn DT1;
private Button button1;
}
}WinForm程序自动更新
使用AutoUpdater.NET自动更新
使用nuget控制台安装包
shell
PM> Install-Package Autoupdater.NET.Official编写退出逻辑
c#
private void AutoUpdater_ApplicationExitEvent()
{
Text = @"Closing application...";
Thread.Sleep(5000);
Application.Exit();
}编写更新版本信息传递逻辑
csharp
private void AutoUpdaterOnParseUpdateInfoEvent(ParseUpdateInfoEventArgs args)
{
try
{
// 加载 XML 数据,args.RemoteData 是 XML 文件路径或 XML 字符串
XDocument xmlDoc = XDocument.Parse(args.RemoteData);
// 更新信息
args.UpdateInfo = new UpdateInfoEventArgs
{
CurrentVersion = xmlDoc.Root.Element("version")?.Value ?? "unknown", // 读取版本号
ChangelogURL = xmlDoc.Root.Element("changelog")?.Value ?? string.Empty, // 读取 changelog URL
DownloadURL = xmlDoc.Root.Element("url")?.Value ?? string.Empty, // 读取下载链接
// 处理 mandatory 节点
Mandatory = new Mandatory
{
Value = bool.TryParse(xmlDoc.Root.Element("mandatory")?.Element("value")?.Value, out bool mandatoryValue) ? mandatoryValue : false,
UpdateMode = Enum.TryParse<Mode>(xmlDoc.Root.Element("mandatory")?.Element("mode")?.Value, true, out var mode) ? mode : Mode.Normal,
MinimumVersion = xmlDoc.Root.Element("mandatory")?.Element("minVersion")?.Value ?? string.Empty
},
// 处理 checksum 节点
//CheckSum = new CheckSum
//{
// Value = xmlDoc.Root.Element("checksum")?.Element("value")?.Value ?? string.Empty,
// HashingAlgorithm = xmlDoc.Root.Element("checksum")?.Element("hashingAlgorithm")?.Value ?? string.Empty
//}
};
}
catch (Exception ex)
{
// 处理解析过程中可能出现的错误
Console.WriteLine("Error parsing XML: " + ex.Message);
}
}编写处理更新逻辑
csharp
private void AutoUpdaterOnCheckForUpdateEvent(UpdateInfoEventArgs args)
{
if (args != null)
{
if (args.IsUpdateAvailable)
{
DialogResult dialogResult;
if (args.Mandatory.Value)
{
dialogResult =
MessageBox.Show(
$@"There is new version {args.CurrentVersion} available. You are using version {args.InstalledVersion}. This is required update. Press Ok to begin updating the application.", @"Update Available",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
else
{
dialogResult =
MessageBox.Show(
$@"There is new version {args.CurrentVersion} available. You are using version {args.InstalledVersion}. Do you want to update the application now?", @"Update Available",
MessageBoxButtons.YesNo,
MessageBoxIcon.Information);
}
// Uncomment the following line if you want to show standard update dialog instead.
AutoUpdater.ShowUpdateForm(args);
if (dialogResult.Equals(DialogResult.Yes) || dialogResult.Equals(DialogResult.OK))
{
try
{
if (AutoUpdater.DownloadUpdate(args))
{
Application.Exit();
}
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, exception.GetType().ToString(), MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
else
{
MessageBox.Show(@"There is no update available please try again later.", @"No update available",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else
{
MessageBox.Show(
@"There is a problem reaching update server please check your internet connection and try again later.",
@"Update check failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}配置AutoUpdater
csharp
//手动处理更新逻辑,可以通过判断本地的版本号对比
AutoUpdater.CheckForUpdateEvent += AutoUpdaterOnCheckForUpdateEvent;
//退出逻辑
AutoUpdater.ApplicationExitEvent += AutoUpdater_ApplicationExitEvent;
//更新版本信息传递,其他非xml格式更新文件
AutoUpdater.ParseUpdateInfoEvent += AutoUpdaterOnParseUpdateInfoEvent;
//指定下载目录
AutoUpdater.DownloadPath = Environment.CurrentDirectory;
//指定提取包含更新文件的zip文件的位置
var currentDirectory = new DirectoryInfo(Environment.CurrentDirectory);
if (currentDirectory.Parent != null)
{
AutoUpdater.InstallationPath = currentDirectory.Parent.FullName;
}
//窗体大小
AutoUpdater.UpdateFormSize = new System.Drawing.Size(800, 600);
AutoUpdater.Start("ftp://abcd@192.168.123.1/AutoUpdaterTest.xml");使用 Scoped Service 进行隔离
问题描述:
前些天给 Asp.Net 项目加了个定时任务,然后第二个Worker运行之后,第一个Worker会失效
- 检查日志没有报错
- 检查数据库发现有死锁,删除死锁后,重启应用
- 死锁复现
问题分析:
两个Worker在运行时候访问了同一个DomainService,怀疑是冲突了,所以会锁表 (只是推测,没有验证具体原因,网上也没搜到相关问题)
解决方案:
尝试使用 Scoped Service 隔离两个Worker 使用这种方式调用IxxxxAppService的doSomething()方法
Csharp
IServiceScope? serviceScope = null;
try
{
serviceScope = provider.CreateScope();
var serviceProvider = serviceScope.ServiceProvider;
var ncAppService = serviceProvider.GetService<IxxxxAppService>();
if (IxxxxAppService != null)
{
IxxxxAppService.doSomething();
}
}
catch (Exception ex)
{
_logger.LogError("worker报错" + ex.Message);
}
finally
{
if (serviceScope != null)
{
serviceScope.Dispose();
}
serviceScope = null;
}将两个Worker都用这种方式编写后,解决问题。
反思
虽然不确定具体问题,但是这样确实有效 其实在一个Worker里编写两个任务代码就可以实现了,开俩定时器就行 这里其实做复杂了,才出现了这种问题。