在vs2019中用C#远程访问fireBird3.0数据库
由于想弄一个小程序,发现fireBird数据库是免费的,并且评价很高。所以下载安装了fireBird3.0 64位版本的数据库,安装模式为supper classic,安装在了DELL笔记本上,充当服务器。导入了一些记录,以做测试。在另一个ASUS电脑上安装了VS2019体验版(免费的,买不起啊),用C#设计了一个WINFORM程序,来访问DELL上的FB数据库。查阅了这么多资料,发现讲EMBED类型的较多,但是讲远程访问的很少,并且也讲的不清楚。最后经过不断的折磨,尝试,终于有结果。考虑到像我这样的朋友,可能会查找一些资料,以期能够帮助他们。
1、 安装哪些访问组件
在VS中,经过以下步骤,添加一些引用,就可以访问FB数据库了。
1)在解决方案上按右键—管理NuGet…
2)浏览—firebird,选择第2项
3)安装
4)成功后,在“引用”项中多出了一些
5)在代码前再添加2个引用
好了,客户端程序已经具备了访问FB数据库的能力了。
2、 客户端程序的代码添加(数据访问代码参考自网上,小作了修改,请原作者见谅)
using FirebirdSql.Data.FirebirdClient;
using FirebirdSql.Data.Services;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace connFireBird
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
string txtFind = "";
txtFind = this.textBox1.Text.Trim();
if(txtFind=="")
{
MessageBox.Show("没有输入姓名,请输入后再操作!");
return;
}
FireBirdHelper fbh = new FireBirdHelper(Application.StartupPath, "computerclass.fdb", "192.168.3.2", true);
string strError = "";
if (!fbh.ConnectTest(out strError))
{
MessageBox.Show("数据库连接不成功,错误信息为:" + strError + "。请检查!");
return;
}
string selSql = "select C.classsimname from classes C inner join users U on C.classid=U.classid where U.peoplename like '" + txtFind + "';";
string strClassName = "";
DataSet ds = fbh.ExecuteSqlGetDs(selSql);
if(ds.Tables[0].Rows.Count==0)
{
label1.Text = "没有找到!";
return;
}
strClassName = ds.Tables[0].Rows[0][0].ToString();
label1.Text = strClassName;
}
}
public class FireBirdHelper
{
private FbConnection _conn = null;
private string _strConn = "";
private readonly string _pathSys;
private readonly string _path;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="pathSys">应用程序路径</param>
/// <param name="path">数据库fdb文件名,以及不包括IP的路径</param>
/// <param name="strIP">数据库所在电脑的IP地址</param>
/// <param name="isServer">true=服务器模式;false=嵌入式模式;</param>
public FireBirdHelper(string pathSys, string path, string strIP, bool isServer = false)
{
_pathSys = pathSys;
_path = path;
_strConn = isServer ? GetConnString_Server(strIP) : GetConnString_Client();
_conn = new FbConnection(_strConn);
}
/// <summary>
/// 服务器式连接
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private string GetConnString_Server(string stringIPAddress)
{
FbConnectionStringBuilder cs = new FbConnectionStringBuilder();
cs.UserID = "SYSDBA";
cs.Password = "masterkey";
cs.Database = _path;
cs.DataSource = stringIPAddress; // "localhost";
cs.Charset ="UTF8" ; // "GB_2312";
cs.Port = 3050;
cs.Dialect = 3;
cs.Role = "";
cs.ConnectionLifeTime = 15;
cs.Pooling = true;
cs.MinPoolSize = 0;
cs.MaxPoolSize = 50;
cs.PacketSize =4096; // 8192
cs.ServerType = FbServerType.Default;
return cs.ToString();
}
/// <summary>
/// 嵌入式连接
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private string GetConnString_Client()
{
FbConnectionStringBuilder cs = new FbConnectionStringBuilder();
cs.ClientLibrary = $"{_pathSys}\\fbembed.dll";
cs.UserID = "SYSDBA";
cs.Password = "masterkey";
cs.Database = _path;
cs.Charset = "UTF8";
cs.ServerType = FbServerType.Embedded;
return cs.ToString();
}
private void MyOpen()
{
if (_conn.State != ConnectionState.Open)
_conn.Open();
}
private void MyClose()
{
if (_conn.State != ConnectionState.Closed)
_conn.Close();
}
/// <summary>
/// 数据库连接测试 (链接目标库)
/// </summary>
/// <param name="di"></param>
/// <param name="errInfo">连接失败时的异常信息</param>
/// <returns></returns>
public bool ConnectTest(out string errInfo)
{
errInfo = string.Empty;
try
{
_conn = new FbConnection(_strConn);
MyOpen();
MyClose();
}
catch (Exception ex)
{
errInfo = $"连接失败。失败原因如下:{ex.Message}";
}
return string.IsNullOrEmpty(errInfo);
}
public DataSet ExecuteSqlGetDs(string sql)
{
DataSet ds = new DataSet();
MyOpen();
FbCommand cmd = new FbCommand(sql, _conn);
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 60;
FbDataAdapter fbAda = new FbDataAdapter(cmd);
fbAda.Fill(ds);
fbAda.Dispose();
cmd.Dispose();
MyClose();
return ds;
}
public DataTable ExecuteSqlGetDt(string sql, int topRows)
{
DataTable dt = new DataTable();
MyOpen();
FbCommand cmd = new FbCommand(sql, _conn);
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 60;
FbDataAdapter fbAda = new FbDataAdapter(cmd);
fbAda.Fill(0, topRows, dt);
fbAda.Dispose();
cmd.Dispose();
MyClose();
return dt;
}
/// <summary>
/// 执行SQL,返回受影响的行数
/// </summary>
public int ExecuteNonQuery(string sql, int timeOut = 5)
{
MyOpen();
FbCommand cmd = new FbCommand(sql, _conn);
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = 60;
int res = cmd.ExecuteNonQuery();
cmd.Dispose();
MyClose();
return res;
}
}
}
3、 但是还是访问不了,出现了
解决方法:在WINDOWS防火墙中,
点击左上“允许或功能通过……”,再点击右下的“允许其他应用”按钮。添加FIREBIRD3.0
选择网络类型,专用网络。
成功如下:
4、 但是还是访问不了。出现了权限不匹配的提示等等(具体画面不想还原了)。查阅了这么多资料,终于在firebird的安装文件夹下,有2个重要的文件里面,找到了一点线索。作为一些修改。如下:
1) 修改firebird.conf,添加2行配置如下:
#WireCrypt = Enabled (for client) / Required (for server)
WireCrypt =Required
WireCrypt = Enabled
2) 修改databases.conf,在最后模仿上面一段,添加内容如下(第1行左边为数据库名,=后面是具体的路径):
computerclass.fdb=C:\Users\xff\Documents\computerclass.fdb
{
RemoteAccess = true
DefaultDbCachePages = 50
}
这里说明一下,早期版本这个文件名可能为aliaes.conf,这个文件是登记一些数据库别名用的。这样,当远程机子访问FB库时,不需要知道具体的路径,只提供前面的库名(别名即可)。另外,为了保险起见,在数据库设计中,也要设置别名为上面的一样名称。
当然,期间也发生了一些小“事故”,例如,把360关了,但后来测试发现这个不影响,主要还是WINDOWS防火墙。还有SQL查询语句写错,出现了SQL 206错误等等。
苦于找不到好的相关的资料,很感谢网络上无私的程序员。身为一名苦苦攀登的小白,在这里致谢了。
2019.7.24