使用 EntityFramework LINQ 的个人通讯簿






4.87/5 (15投票s)
一个简单的个人地址程序,演示如何使用 Entity Framework 在 CRUD(创建、读取、更新、删除)操作中执行 LINQ 查询。
引言
本项目是《面向初学者的 ADO.NET 数据库操作》的第二个版本。它不是一个完美的程序,而是一个简单的“个人地址程序”,使用 Windows Forms 控件和功能来演示如何使用 LINQ 查询在 Entity Framework 中执行创建(插入)、读取(检索)、更新(修改)和删除操作。
我重写这个程序的原因是:2010 年,我弟弟 Ali 在 Codeproject.com 上看到《面向初学者的 ADO.NET 数据库操作》后问我:“你能在表单上也显示这个人的照片吗?”我说:“如果我有时间,我可以做到。”不料,他于 2011 年 10 月因心脏病发作去世,享年 49 岁。
现在,我想实现他的愿望,决定重写这个应用程序。这个第二个版本是献给 Ali 的。
我(主要)使用 Entity Framework LINQ 查询进行数据访问,并且如 Ali 所愿,在表单上显示照片。
因此,数据库中的第一个测试记录是 Ali 的记录,包含他的照片。我希望他在新世界里安息。
它是如何工作的?
如果您第一次在 Visual Studio 2010 中打开解决方案,它将:
- A. 检查 SQLServer 是否未运行、已停止或已暂停。
- B. 检查 SQLServer 上是否存在数据库。
- 1. 如果数据库不存在 --> 在 SQLServer 上创建数据库
- 2. 检查表是否存在。如果不存在 --> 运行 SQL 脚本在数据库中创建表。
- C. 检查数据库是否存在但表不存在。
- 1. 运行 SQL 脚本创建表并插入第一个测试记录。
- D. 目前数据库和表已成功创建。
- 1. 使用 LINQ 查询获取 PersonTable 中的记录数。
- 2. 如果表中有记录,则使用
FnRefreshAll();
显示第一条记录。 - 3. 如果表中没有记录:
- a-运行方法
FnInsertFirstTestRecordWithVarbinaryImage()
插入第一个测试记录。 - b-使用方法
FnRefreshAll()
显示第一个记录。
您可以使用“Next、Previous、First、Last”按钮浏览记录。
判断 SQLServer 是否正在运行、已停止或已暂停
这是一个小方法,用于判断您的 SQLServer 是正在运行、已停止还是已暂停。
public static bool FnCheckSQLServerIsNotRunning()
{
ServiceController sctl= new ServiceController("MSSQL$SQLEXPRESS");
if (sctl.Status != ServiceControllerStatus.Running || sctl.Status == ServiceControllerStatus.Stopped || sctl.Status == ServiceControllerStatus.Paused)
{
//sctl.Start();
return true;
}
return false;
}
检查数据库在 SQLServer 上是否存在
以下是检查数据库是否在 SQLServer 上存在的方法。
public static bool FnCheckDatabaseExists(string strDBname)
{
//using Microsoft.SqlServer.Management.Smo; to use Server class
Server dbServer = new Server(FnGetSqlServerName());
if (dbServer.Databases[strDBname] != null)
{
return true;
}
return false;
}
获取您 PC 上的 SQLServer 名称
您可以使用以下方法查找您计算机上的 SQLServer 名称。
//loop through ServiceController; try to get "MSSQL$SQLEXPRESS" to build PCName\SQLEXPRESS as strSqlServerName
private static string FnGetSqlServerName()
{
//local PC name
string strPCname = Environment.MachineName;
// service name of SQL Server Express
string strInstance = "MSSQL$SQLEXPRESS";
string strSqlServerName = string.Empty;
// Add Reference: System.ServiceProcess;
ServiceController[] services = ServiceController.GetServices();
foreach (ServiceController service in services)
{
if (service == null)
continue;
string strServicename = service.ServiceName;
if (strServicename.Contains(strInstance))>
{
strSqlServerName = strServicename;
}
}//foreach
int startIndex = strSqlServerName.IndexOf("$");
if (startIndex > -1)
{
// strSqlServerName=YourPCName\SQLEXPRESS;
strSqlServerName = strPCname + @"\" + strSqlServerName.Substring(startIndex + 1);
}
return strSqlServerName;
}
在 SQLServer 上创建数据库
一旦您有了 SQLServer 和数据库名称,您就可以使用下面的方法在 SQLServer 上创建数据库。
public static void FnCreateDatabase(string strDBname)
{
// Add Reference: Microsoft.SqlServer.Smo.dll which is in project folder "ScriptsDLLs"
Server dbServer = new Server(FnGetSqlServerName());
Database myDatabase = new Database(dbServer, strDBname);
myDatabase.Create();
}
检查 SQLServer 数据库中是否存在表
这是检查数据库中是否存在表的方法。返回值是 true(找到)/false(未找到)。
public static bool FnCheckDatabaseTableExists(string strDBname, string strTablename)
{
// Add Reference: Microsoft.SqlServer.Smo.dll which is in project folder "ScriptsDLLs"
Server dbServer = new Server(FnGetSqlServerName());
Database myDatabase = dbServer.Databases[strDBname];
// loop through all the tables of myDatabase
foreach (Table myTable in myDatabase.Tables)
{
if (myTable.Name == strTablename)
{
return true; //table found
}//if
}//foreach
return false; //table not found
}
使用 ADO.NET 运行 SQL 脚本创建表 "PersonTable"
public static void FnRunSQLScriptToCreatePersonTable(string strPathFile)
{
Assembly asm = Assembly.GetEntryAssembly();
string appDir = Path.GetDirectoryName(asm.Location);
string filePath = Path.Combine(appDir, strPathFile);
FileInfo file = new FileInfo(filePath);
string strScript = file.OpenText().ReadToEnd();
strScript = strScript.Replace("GO\r\n", "");
using (SqlConnection conn = new SqlConnection(FnBuildConnectionString()))
{
conn.Open();
SqlCommand cmd = new SqlCommand(strScript, conn);
try
{
cmd.ExecuteNonQuery();
}
catch (Exception excp)
{
throw;
}
}//using
}
使用 Entity Framework 插入/保存带 Varbinary(MAX) 数据类型的第一个测试记录
以下是使用 Entity Framework 插入带 Varbinary(MAX) 的记录的方法。
public static void FnInsertFirstTestRecordWithVarbinaryImage()
{
using (pdContext = new PersonDatabaseEntities())
{
#region save/store a field of type "varbinary(max)" into SQLServer using Entity Framework;
//retrieve this file from file system and store it in a byte array
//Creates and returns an instance of the requested type
PersonTable pTable = pdContext.PersonTables.CreateObject();
//Opens a binary file, reads the contents of the file into a byte array, and then closes the file
pTable.Photo = File.ReadAllBytes(@"..\..\Resources\ali.jpg");
#endregion
//-----------------------------------------------
pTable.FirstName = "Ali";
pTable.LastName = "Altindag";
pTable.Title = "Restaurant Manager";
pTable.Country = "Turkey";
pTable.City = "Pazarcik";
pTable.Notes = "REST IN PEACE." + Environment.NewLine + "Ali, my brother, was born in Pazarcik-Turkey, studied and lived many years in Germany, He then moved to London in 1990.
Unexpectedly, he passed away in Oct'2011 from heart attack at 49. It was him to persuade me to rewrite the first version of this application.
He asked me in 2010 when he saw the first version of the application on Codeproject.com: -Can you show photos as well on the form ?.
I told him to start rewriting it sometime. Now to fulfill his wish I started rewriting the application using the Entity Framework and displaying photos.
Therefore the first record in database is with Ali's photo";
//------------------------------------------------
// Add the new object "pTable" to the "pdContext"
pdContext.PersonTables.AddObject(pTable);
//------------------------------------------------
try
{
//save new person to the data source
pdContext.SaveChanges();
}
catch (Exception excp)
{
throw new Exception("Error: " + excp.Message);
}//try-catch
}//using
}
工具栏按钮的使用:NEW
如果您点击“New”按钮,表单将显示如下:
您可以输入新记录信息,选择照片/图像,然后点击“Save”按钮。只有“Save”、“Refresh”和“Exit”按钮可用。如果未选择照片,则“nophoto.jpg”将插入到表中。
如果点击“New”按钮,将调用以下方法和操作:
FnEnableDisableToolStripButtons(false, true,false, false, true);
用于启用/禁用工具栏上的按钮。FnClearAllTextBoxes(this.Controls);
用于清除文本框。FnEnableDisableTextBox(this.Controls, true)
用于启用文本框以输入信息。FnChangeTextAndColor(this.textBoxHeader, "New record", Color.Red);
用于更改文本框“textBoxHeader”的文本和颜色。this.textboxFirstname.Focus();
this.panelSelectNewImage.Visible = true;
this.panelNavigation.Enabled = false;
pictureBox1.Image = Properties.Resources.nophoto;
在 pictureBox1 中显示 Resources 中的 nophoto.jpg
如果未输入信息并点击“Save”按钮,将显示警告消息,强制用户至少输入“First Name”和“Last Name”。
“Select new image or photo”按钮用于在 PictureBox 中显示“jpg/png/gif”图像。
private void btSelectNewimage_Click(object sender, EventArgs e)
{
pictureBox1.Image = null;
using (OpenFileDialog dlg = new OpenFileDialog())
{
dlg.Filter = "Image Files(jpg/png/gif)|*.jpg;*.png; *.gif";
//or
//dlg.Filter = @"JPEG Files (*.jpeg)|*.jpeg|PNG Files (*.png)|*.png|JPG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif";
if (dlg.ShowDialog() == DialogResult.OK)
{
// assign selected photo/image to the PictureBox.Image property
pictureBox1.Image = Image.FromFile(dlg.FileName);
//assign the image name to properties declared in frmPersonalAddress.cs
this.strNewImageFileName = dlg.FileName;
boNewimageSelected = true; //user selected a new image;
}//if
}//using
}
工具栏按钮的使用:Save
输入一些信息、选择照片并点击“Save”按钮后,将执行以下方法调用和操作。
FnCheckFirstLastNameExistInDB(this.textboxFirstname.Text, this.textboxLastname.Text))
检查姓和名是否存在于数据库中。FnSaveRecord(this, boNewimageSelected);
保存新记录。FnEnableDisableToolStripButtons(true, false, true, true, true);
启用/禁用工具栏上的按钮。this.panelNavigation.Enabled = true;
启用面板“panelNavigation”中的按钮。this.textboxFirstname.Focus();
FnChangeTextAndColorInPanelSelectNewImage(this.textBoxHeader, "Person details", Color.Blue, this.panelSelectNewImage.Visible = false);
更改“textBoxHeader”的文本/颜色,并使面板“panelSelectNewImage”不可见。FnRefreshAll();
刷新并显示第一条记录。
private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
//get name of button clicked on ToolStrip
string strButtonText = toolStripStatusLabel1.Text = e.ClickedItem.ToString();
switch (strButtonText)
{
case "Save":
//force user to enter firstname and lastname
if (string.IsNullOrEmpty(this.textboxFirstname.Text) && string.IsNullOrEmpty(this.textboxLastname.Text))
{
MessageBox.Show("Please enter First Name and Last Name", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
else
{
//check whether the new record with first+last name exists in the database
if (DALHelpers.FnCheckFirstLastNameExistInDB(this.textboxFirstname.Text, this.textboxLastname.Text))
{
MessageBox.Show("First Name and Last Name already exist in database", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
//in order to have access to all of public properties in "frmPersonal Address" class from DALHelpers class we pass as this "frmPersonalAddress" class
DALHelpers.FnSaveRecord(this, boNewimageSelected);
MessageBox.Show("New record has been inserted successfully...");
FnEnableDisableToolStripButtons(true, false, true, true, true);
this.panelNavigation.Enabled = true;
this.textboxFirstname.Focus();
DALHelpers.FnChangeTextAndColorInPanelSelectNewImage(this.textBoxHeader, "Person details", Color.Blue, this.panelSelectNewImage.Visible = false);
FnRefreshAll();
}//else
break;
}//switch
}
检查通过姓和名的新记录是否存在于数据库中
以下是用于查找通过姓和名的新记录是否存在于数据库中的方法:带有 lambda 表达式的 Entity Framework LINQ 查询
public static bool FnCheckFirstLastNameExistInDB(string strFname, string strLname)
{
pdContext = new PersonDatabaseEntities();
//LINQ query with lambda expression
var vpt = pdContext.PersonTables.Where(c => c.FirstName.Equals(strFname) && c.LastName.Equals(strLname));
if (vpt.Any())
{
return true; //record exists.
}
return false;//record does not exist.
}
方法的使用:DALHelpers.FnSaveRecord(this, boNewimageSelected);
我们传递 2 个参数:this 和 boNewimageSelected
。为了从 "DALHelpers
" 访问 "frmPersonalAddress
" 中的所有公共属性,我们将 "frmPersonalAddress
" 类作为 "this" 传递。"boNewimageSelected
" 是一个静态布尔变量,在方法 "private void btSelectNewimage_Click(object sender, EventArgs e)" 中保存 true 或 false;也就是说,它将指示是否选择了照片/图像。如果未选择照片,我们从 Resources\nophoto.jpg 将 "nophoto.jpg" 分配给字符串 "strNewImageFileName
",以便可以将文件的内容读入字节数组。然后,我们可以使用 LINQ 查询保存带有 jpg/gif/png 图像/照片的新记录,其数据类型为 VARBINARY(MAX)。
使用 Entity Framework LINQ 插入/保存带有选定图像的新记录到数据库中
public static void FnSaveRecord(frmPersonalAddress frmPA, bool boNewimageselected)
{
using (pdContext = new PersonDatabaseEntities())
{
try
{
#region make photo ready to be inserted
//Creates and returns an instance of the requested type
PersonTable ppersonnew = pdContext.PersonTables.CreateObject();
//in case user did not select a new image--> insert nophoto.jpg
if (boNewimageselected == false)
{
frmPA.strNewImageFileName = @"..\..\Resources\nophoto.jpg";
}
//Opens a binary file, reads the contents of the file into a byte array, and then closes the file
ppersonnew.Photo = File.ReadAllBytes(frmPA.strNewImageFileName);
#endregion
ppersonnew.FirstName = frmPA.strFirstname;
ppersonnew.LastName = frmPA.strLastname;
ppersonnew.Title = frmPA.strTitle;
ppersonnew.City = frmPA.strCity;
ppersonnew.Country = frmPA.strCountry;
ppersonnew.Notes = frmPA.strNotes;
//------- save --------------------------------
pdContext.PersonTables.AddObject(ppersonnew);
pdContext.SaveChanges();
//----------------------------------------------
}
catch (Exception excp)
{
throw new Exception(excp.Message);
}//try-catch
}//using
}
工具栏按钮的使用:Delete
在删除记录的情况下,只有“Save”按钮被禁用。当点击“Delete”按钮时,用户将被询问是否删除记录。如果选择“是”,它将尝试通过 PersonID 删除记录。返回值为 true(已删除)或 false(未删除)。通过 PersonID 删除记录后,它将调用方法“FnRefreshAll()
和 FnSetButtonTextEditToTextUpdate(this.editToolStripButton, "Edit")
”。
private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
//get name of button clicked on ToolStrip
string strButtonText = toolStripStatusLabel1.Text = e.ClickedItem.ToString();
switch (strButtonText)
{
case "Delete":
if (DALHelpers.FnDeleteCurrentRecord(pdContext, iCurrentPersonID))
{
toolStripStatusLabel1.Text = "Record deleted...";
FnRefreshAll();
this.textboxFirstname.Focus();
}//if
break;
}//switch
}
使用 Entity Framework LINQ 删除当前记录
//It returns true if record is deleted otherwise false
public static bool FnDeleteCurrentRecord(PersonDatabaseEntities pdContext, int iCurrentPersonID)
{
bool boRet = false;
DialogResult dr = MessageBox.Show("Are you sure you want to delete this record ? ", "Confirm deleting", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dr == DialogResult.Yes)
{
using (pdContext = new PersonDatabaseEntities())
{
PersonTable pperson = pdContext.PersonTables.Where(c => c.PersonID == iCurrentPersonID).FirstOrDefault();
if (pperson != null)
{
pdContext.PersonTables.DeleteObject(pperson);
pdContext.SaveChanges();
boRet = true;
}//if
}//using
}//if
return boRet;
}
工具栏按钮的使用:Refresh 和方法 "FnRefreshAll()"
方法 "DALHelpers.FnRefreshAll();
" 的使用
方法 "FnRefreshAll()
" 从表中获取第一条记录,并将其显示在文本框中,将 VARBINARY(MAX) 数据类型的照片显示在 PictureBox 中。通过 LINQ 查询,我们返回表中可用记录的数量,并检查表中是否有任何记录。如果有一条或多条记录,我们尝试运行一个 SELECT LINQ 查询,使用 FirstOrDefault()
获取第一条记录。如果找不到任何匹配的记录,FirstOrDefault()
可以返回 null;这意味着表为空,因此我们将显示消息 "No records exist in database"。如果您删除了第一个测试记录,可能会发生这种情况。
使用 Entity Framework LINQ 在 PictureBox 中显示数据库表的第一条记录及其图像
private void FnRefreshAll()
{
using (pdContext = new PersonDatabaseEntities())
{
#region check record and show image in pictureBox
var ptRecordCount = (from ptbl in pdContext.PersonTables
select ptbl).Count();
//check whether table has any records
if (ptRecordCount > 0)
{
//get first record
var ptResult = (from ptbl in pdContext.PersonTables
select ptbl).Take(1).FirstOrDefault();
#region check just in case if first record exists
if (ptResult != null)
{
#region if-else
//pass ProductPhotoID of first record and check record exist
if (DALHelpers.FnCheckRecordByID(ptResult.PersonID))
{
#region if-else; record exist and check Photo exists
//make use of property "myPersontableProperty1" which is declared in DALHelper.cs
if (DALHelpers.myPersontableProperty1.Photo != null)
{
#region display varbinary(MAX) field "Photo" in PictureBox;
//convert varbinary(MAX) field "Photo" to byte Array
byte[] byteArrayIn = DALHelpers.myPersontableProperty1.Photo.ToArray();
//Convert byte[] array to Image and display in PictureBox
pictureBox1.Image = DALHelpers.FnByteArrayToImage(byteArrayIn);
#endregion
FnDisplayRecordsInTextBoxes(ptResult, ptRecordCount);
DALHelpers.FnEnableDisableTextBox(this.Controls, false);
}
else //no photo -> display nophoto.jpg
{
// get/show nohoto.jpg from project folder "Resources"
pictureBox1.Image = Properties.Resources.nophoto;
}//else
#endregion
}
else //DALHelpers.myPersontableProperty1.Photo == null->no photo display nophoto.jpg
{
// get/show nophoto.jpg from project folder "Resources"
pictureBox1.Image = Properties.Resources.nophoto;
}//else
#endregion
}//if (phResult != null)
else
{
// get/show nohoto.jpg from project folder "Resources"
pictureBox1.Image = Properties.Resources.nophoto;
FnDisplayRecordsInTextBoxes(ptResult, ptRecordCount);
DALHelpers.FnEnableDisableTextBox(this.Controls, false);
}//else
#endregion
FnEnableDisableToolStripButtons(true, false, true, true, true);
this.panelNavigation.Enabled = true;
DALHelpers.FnChangeTextAndColorInPanelSelectNewImage(this.textBoxHeader, "Person details", Color.Blue, this.panelSelectNewImage.Visible = false);
}//if no records; table is empty
else
{
#region no records; table is empty
// get/show nohoto.jpg from project folder "Resources"
pictureBox1.Image = Properties.Resources.nophoto;
DALHelpers.FnClearAllTextBoxes(this.Controls);
DALHelpers.FnEnableDisableTextBox(this.Controls, false);
this.panelNavigation.Enabled = false;
DALHelpers.FnChangeTextAndColorInPanelSelectNewImage(this.textBoxHeader, "No records exist in database", Color.Blue, this.panelSelectNewImage.Visible = false);
FnEnableDisableToolStripButtons(true, false, false, false, false);
#endregion
}
#endregion
}//using
boNewimageSelected = false;
}
工具栏按钮的使用:Edit 和 Update
如果在浏览记录时点击“Edit”按钮,则“Edit”按钮的文本将变为“Update”,并且文本框中的文本将变为“Update details”,以向用户显示处于编辑/更新模式。文本框和“Select new image or photo”按钮将启用,可供编辑。
“Edit”按钮执行以下操作:
FnEnableDisableToolStripButtons(false, false, true, true, true);
用于启用/禁用工具栏按钮:(新建、保存、删除、编辑、刷新)。FnEnableDisableTextBox(this.Controls, true);
用于启用表单上的文本框。FnSetButtonTextEditToTextUpdate(this.editToolStripButton, "Update");
用于将“Edit”按钮的文本更改为“Update”。this.panelNavigation.Enabled = true;
启用面板“panelNavigation”中的按钮。this.textboxFirstname.Focus();
FnChangeTextAndColorInPanelSelectNewImage(this.textBoxHeader, "Update details", Color.Blue, this.panelSelectNewImage.Visible = true);
用于更改“textBoxHeader”的文本/颜色,并使面板“panelSelectNewImage”可见。
“Update”按钮执行以下操作:
FnUpdateRecord(this);
用于更新当前记录。FnSetButtonTextEditToTextUpdate(this.editToolStripButton, "Edit");
用于将“Update”按钮的文本更改为“Edit”。FnEnableDisableToolStripButtons(this.newToolStripButton, true);
用于启用“New”工具栏按钮。FnEnableDisableTextBox(this.Controls, false);
用于禁用表单上的文本框。this.textboxFirstname.Focus();
FnChangeTextAndColorInPanelSelectNewImage(this.textBoxHeader, "Person details", Color.Blue, this.panelSelectNewImage.Visible = false);
更改“textBoxHeader”的文本/颜色,并使面板“panelSelectNewImage”不可见。
使用 Entity Framework LINQ 更新记录
private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
//get name of button clicked on ToolStrip
string strButtonText = toolStripStatusLabel1.Text = e.ClickedItem.ToString();
switch (strButtonText)
{
case "Update":
if (DALHelpers.FnUpdateRecord(this, boNewimageselected))
{
DALHelpers.FnSetButtonTextEditToTextUpdate(this.editToolStripButton, "Edit");
DALHelpers.FnEnableDisableToolStripButtons(this.newToolStripButton, true);
DALHelpers.FnEnableDisableTextBox(this.Controls, false);
this.textboxFirstname.Focus();
DALHelpers.FnChangeTextAndColorInPanelSelectNewImage(this.textBoxHeader, "Person details", Color.Blue, this.panelSelectNewImage.Visible = false);
}//if
this.panelNavigation.Enabled = true;
break;
}//switch
}
public static bool FnUpdateRecord(frmPersonalAddress frm1, bool boNewimageselected))
{
bool bRet=false;
using(pdContext=new PersonDatabaseEntities())
{
//LINQ query with lambda expression
var pperson = pdContext.PersonTables.Where(c => c.PersonID .Equals(frm1.iCurrentPersonID)).FirstOrDefault();
if (pperson != null)
{
#region make photo ready to be inserted
if (boNewimageselected == true)
{
//Opens a binary file, reads the contents of the file into a byte array, and then closes the file
pperson.Photo = File.ReadAllBytes(frm1.strNewImageFileName);
}
#endregion
//access to public properties in Form frmPersonalAddress
pperson.FirstName = frm1.strFirstname;
pperson.LastName = frm1.strLastname;
pperson.Title = frm1.strTitle;
pperson.City = frm1.strCity;
pperson.Country = frm1.strCountry;
pdContext.SaveChanges();
bRet = true;
}//if
}//using
return bRet;
}
工具栏按钮的使用:Exit
关于“Exit”按钮没有什么太多可解释的,但我认为值得一提的是,如果用户点击“X”按钮或表单菜单中的“Close ALT+F4”,表单会关闭。
用户点击“Exit”按钮
public static void FnExit()
{
DialogResult dr = MessageBox.Show("Are you sure You want to exit application?", "Confirm Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (dr == DialogResult.Yes)
{
Application.Exit();
}
}
方法 FnExit()
不言自明。
用户点击“X”按钮或表单菜单中的“Close ALT+F4”
每当用户在表单关闭之前关闭表单时发生,并指定关闭原因及其事件。
private void frmPersonalAddress_FormClosing(object sender, FormClosingEventArgs e)
{
DALHelpers.FnFormClosing(e);
}
public static void FnFormClosing(FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
if (DialogResult.No == MessageBox.Show("Are you sure You want to exit application?", "Confirm Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2))
e.Cancel = true;
else
Application.Exit();
}
}
使用 Entity Framework 在 PictureBox 中显示 Varbinary(MAX) 数据类型的图像或照片
int iID=1;
using (pdContext = new PersonDatabaseEntities())
{
var personRecord = (from ptbl in pdContext.PersonTables
where ptbl.PersonID == iID
select ptbl).FirstOrDefault();
if (personRecord !=null)
{
//convert varbinary(MAX) field "Photo" to byte Array
byte[] byteArrayIn = DALHelpers.myPersontableProperty1.Photo.ToArray();
//Convert byte[] array to Image and display in PictureBox
pictureBox1.Image = DALHelpers.FnByteArrayToImage(byteArrayIn);
}//if
}//using
//Convert byte[] array to Image
public static Image FnByteArrayToImage(byte[] byteArrayIn)
{
MemoryStream memstream = new MemoryStream(byteArrayIn);
Image ret = Image.FromStream(memstream);
return ret;
}
使用 ADO.NET 和 LINQ 查询在 PictureBox 中显示“image”数据类型的图像或照片:Northwind-Employee
如果您安装并使用 Northwind 中的“Employees”表,您将看到只有 9 条记录,其中图像带有 78 字节的标题前缀。要显示带有这 9 条记录的图像,您可以使用以下 3 种方法。
int iId = 5;
pictureBox1.Image = FnRetrieveImage(iId);
private Image FnRetrieveImage(int iEmployeeid)
{
SqlConnection connect = new SqlConnection(strConString);
connect.Open();
string sSql = "select Photo from Employees where EmployeeID = '" + iID + "' ";
SqlCommand command = new SqlCommand(sSql, connect);
SqlDataAdapter dp = new SqlDataAdapter(command);
DataSet ds = new DataSet();
dp.Fill(ds, "Employees");
int iCoount = ds.Tables["Employees"].Rows.Count;
DataRow dr = ds.Tables["Employees"].Rows[0];
MemoryStream ms = new MemoryStream();
Bitmap bm = default(Bitmap);
byte[] arData = (Byte[])(ds.Tables["Employees"].Rows[iCoount - 1]["Photo"]);
ms.Write(arData, 78, arData.Length - 78);
bm = new Bitmap(ms);
return bm;
}
int iId=1;
pictureBox1.Image = FnRetrieveImage(iId);
private Image FnRetrieveImage(int iEmployeeid)
{
Image image = null;
using (SqlConnection connection = new SqlConnection(strConString))
{
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT Photo FROM Employees WHERE EmployeeID = @EmpID";
command.Parameters.AddWithValue("@EmpID", iEmployeeid);
connection.Open();
byte[] imageData = (byte[])command.ExecuteScalar();
MemoryStream memStream = new MemoryStream(imageData);
memStream.Write(imageData, 78, imageData.Length - 78);
image = Bitmap.FromStream(memStream);
}//using
}//using
return image;
}
using (dbContext = new NorthwindEntities())
{
var photoRecord = (from accom in dbContext.Employees
where accom.EmployeeID == 1
select accom).FirstOrDefault();
if (photoRecord != null)
{
byte[] byteArrayIn = photoRecord.Photo.ToArray();
MemoryStream memStream = new MemoryStream(byteArrayIn);
// the database BLOB field contains normally only the image itself.
//but this is not the case with Northwind, in which images are prefixed with a 78-byte header.
memStream.Write(byteArrayIn, 78, byteArrayIn.Length - 78);
pictureBox1.Image = Bitmap.FromStream(memStream);
}
}//using
假设您使用以下方法(示例 1 - 使用 ADO.NET,示例 1 - 使用 LINQ)向 Northwind-Employees 表中插入带有“gif/png/jpg”图像的新记录,并希望调用上述方法来显示图像。插入将执行,但使用示例 1、2、3 的显示将失败(错误消息:参数无效或类似),因为 Northwind-Employees 中的图像带有 78 字节的标题前缀。在这种情况下,请使用方法“FnDisplayImageExampleADO.NET()
”和/或“FnDisplayImageExampleWithLINQ()
”进行显示。
插入带图像的记录:ADO.NET
示例 1 - 使用 ADO.NET
private void FnInsertImageIntoEmployeesWithADONET()
{
SqlConnection conn = new SqlConnection("YourConnectionString");
string strSql = "INSERT INTO Employees (FirstName, LastName, Photo) VALUES ('TestFirstname', 'TestLastname', @image)";
conn.Open();
byte[] image = File.ReadAllBytes(@"C:\Users\Public\Pictures\Sample Pictures\Tulips.gif");
SqlCommand sqlCommand = new SqlCommand(strSql, conn);
sqlCommand.Parameters.AddWithValue("@image", image);
sqlCommand.ExecuteNonQuery();
this.labelMsg.Text = "Saved...";
}
插入带图像的记录:LINQ
示例 1 - 使用 LINQ
private void FnInsertImageIntoEmployeesWithLINQ()
{
using (dbContext = new NorthwindEntities())
{
try
{
#region make photo ready to be inserted
//creates and returns an instance of the requested type
Employee ppersonnew=dbContext.Employees.CreateObject();
//opens a binary file, reads the contents of the file into a byte array, and then closes the file
ppersonnew.Photo = File.ReadAllBytes(@"C:\Users\Public\Pictures\Sample Pictures\Penguins.jpg");
#endregion
ppersonnew.FirstName = "TestFNLinq";
ppersonnew.LastName = "TestLNLinq";
//------- save -------------------------
dbContext.Employees.AddObject(ppersonnew);
dbContext.SaveChanges();
//----------------------------------------------
this.labelMsg.Text = "Saved...";
}
catch (Exception excp)
{
throw new Exception(excp.Message);
}//try-catch
}//using
}
运行方法 "FnInsertImageIntoEmployeesWithADONET()
" 和 "FnInsertImageIntoEmployeesWithLINQ
" 后,您可以使用以下方法在 PictureBox 中显示图像:
示例:使用 ADO.NET 显示图像
private void FnDisplayImageExampleADO.NET()
{
int iID = 11;//i.e : the new record
string sSql = "select Photo from Employees where EmployeeID = '" + iID + "' ";
SqlConnection connect = new SqlConnection(strConString);
connect.Open();
SqlDataAdapter dataAdapter = new SqlDataAdapter(new SqlCommand(sSql, connect));
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet);
if (dataSet.Tables[0].Rows.Count == 1)
{
Byte[] data = new Byte[0];
data = (Byte[])(dataSet.Tables[0].Rows[0]["Photo"]);
MemoryStream mem = new MemoryStream(data);
pictureBox1.Image = Image.FromStream(mem);
}
示例:使用 LINQ 显示图像
private void FnDisplayImageExampleWithLINQ()
{
int iId=11; //i.e : the new record
using (dbContext = new NorthwindEntities())
{
var photoRecord = (from accom in dbContext.Employees
where accom.EmployeeID == iId
select accom).FirstOrDefault();
if (photoRecord != null)
{
byte[] byteArrayIn = photoRecord.Photo.ToArray();
MemoryStream stream = new MemoryStream(byteArrayIn);
//converting the byte array of image to the real image
pictureBox1.Image = Image.FromStream(stream);
}//if
}//using
}
历史
- 2012 年 6 月 11 日:初始版本
- 2012 年 6 月 20 日:添加了
FnCheckFirstLastNameExistInDB(this.textboxFirstname.Text, this.textboxLastname.Text)
- 在插入新记录之前检查数据库中是否已存在。 - 2012 年 6 月 20 日:添加了
FnCheckSQLServerIsNotRunning()
- 判断 SQLServer 是否正在运行。 - 2012 年 7 月 9 日:微小更改和各种小改进。
结论
正如您所看到的,这个应用程序还有很多改进的空间,它并不是一个完美的地址程序。我希望这里提供的一些技巧和窍门能提高您使用 C# 的效率,并作为使用 Entity Framework LINQ 执行 CRUD 操作的一个良好开端。就我个人而言,我在我的 Windows Form 应用程序中使用了大部分这些方法。
“幸福降临给那些给他人带来幸福的人。” (琐罗亚斯德)。