Winform+DevExpress框架之独立图片存储解决方案|C/S框架网
Winform+DevExpress框架之独立图片存储解决方案|C/S框架网
C/S框架网发布的Winform+DevExpress快速开发框架为用户提供强大技术支持以及高效的快速开发能力,配套有专业的开发文档,即时的在线服务,为用户高效敏捷开发提供有力保障。
我们在开发大型软件系统时,经常会遇到存储图片资源需求,终端用户需要提交本地图片到应用服务器或数据库服务器等,作者使用过以下几种图片资源存储策略。
关于Winform系统图片存储策略,有以下几种方案参考:
1. 存在独立的资料表(如:dt_Image),与系统结合紧密度最高,实现最简单。
2. 访问IIS服务器,使用URL方式访问图片,需要部署IIS服务器,客户端要能访问IIS服务器。
3. 本机缓存机制+在线单个图片动态获取。
4. FTP服务器,阿里OSS存储等。
使用独立图片表存储图片资源有以下优势:
1.图片资源与业务数据完全分离。
2.图片资源可以跨服务器部署、可扩展支持其它图片存储策略。
3.与系统结合紧密度最高,实现简单,代码复用。
4.易维护性。
本文将重点阐述在VS开发环境下使用ADO.NET组件独立存储图片解决方案。
效果图:
一、创建独立的图片表(dt_Image)
下面是dt_Image表结构对应的ORM模型,建表SQL请下载附件。
C# Code:
///<summary>
/// ORM模型, 数据表:dt_Image,由ClassGenerator自动生成
/// </summary>
[ORM_TableAttribute("dt_Image", "ImgID", false)]
public sealed class dt_Image
{
public static string __TableName = "dt_Image";
public static string __KeyName = "ImgID";
[ORM_FieldAttribute(DbType.Int32, 4, true, false, false, false, false)]
public static string isid = "isid";
[ORM_FieldAttribute(DbType.String, 32, false, true, true, false, false)]
public static string ImgID = "ImgID";
[ORM_FieldAttribute(DbType.String, 20, false, true, false, false, false)]
public static string DocType = "DocType";
[ORM_FieldAttribute(DbType.String, 50, false, true, false, true, false)]
public static string DocNo = "DocNo";
[ORM_FieldAttribute(DbType.String, 20, false, true, false, false, false)]
public static string DocTag = "DocTag";
[ORM_FieldAttribute(DbType.Binary, 52428800, false, true, false, false, false)]
public static string ImgSmall = "ImgSmall";
[ORM_FieldAttribute(DbType.Binary, 52428800, false, true, false, false, false)]
public static string ImgLarge = "ImgLarge";
[ORM_FieldAttribute(DbType.DateTime, 8, false, true, false, false, false)]
public static string CreationDate = "CreationDate";
[ORM_FieldAttribute(DbType.String, 20, false, true, false, false, false)]
public static string CreatedBy = "CreatedBy";
}
//来源:C/S框架网(www.csframework.com) QQ:23404761
///<summary>
/// ORM模型, 数据表:dt_Image,由ClassGenerator自动生成
/// </summary>
[ORM_TableAttribute("dt_Image", "ImgID", false)]
public sealed class dt_Image
{
public static string __TableName = "dt_Image";
public static string __KeyName = "ImgID";
[ORM_FieldAttribute(DbType.Int32, 4, true, false, false, false, false)]
public static string isid = "isid";
[ORM_FieldAttribute(DbType.String, 32, false, true, true, false, false)]
public static string ImgID = "ImgID";
[ORM_FieldAttribute(DbType.String, 20, false, true, false, false, false)]
public static string DocType = "DocType";
[ORM_FieldAttribute(DbType.String, 50, false, true, false, true, false)]
public static string DocNo = "DocNo";
[ORM_FieldAttribute(DbType.String, 20, false, true, false, false, false)]
public static string DocTag = "DocTag";
[ORM_FieldAttribute(DbType.Binary, 52428800, false, true, false, false, false)]
public static string ImgSmall = "ImgSmall";
[ORM_FieldAttribute(DbType.Binary, 52428800, false, true, false, false, false)]
public static string ImgLarge = "ImgLarge";
[ORM_FieldAttribute(DbType.DateTime, 8, false, true, false, false, false)]
public static string CreationDate = "CreationDate";
[ORM_FieldAttribute(DbType.String, 20, false, true, false, false, false)]
public static string CreatedBy = "CreatedBy";
}
//来源:C/S框架网(www.csframework.com) QQ:23404761
二、保存数据前调用 BLL.CreateSaveData方法完成数据采集
C# Code:
/// <summary>
/// 创建用于保存的临时数据,包含主表、明细表、图片表
/// </summary>
/// <param name="sourceData">当前业务单据数据集</param>
/// <returns></returns>
public override DataSet CreateSaveData(DataSet sourceData)
{
this.DataBindRow.EndEdit();
DataSet save = new DataSet();
save.Tables.Add(this.DataBinder.Copy());//将<主表>添加到数据集
this.UpdateCommonFieldsValue(save.Tables[0]); //更新<主表>公共字段数据
//收集明细表数据
DataTable detail = sourceData.Tables[tb_PIs.__TableName].Copy();
this.UpdateCommonFieldsValue(detail); //更新明细表的公共字段数据
save.Tables.Add(detail); //将<明细表>添加到数据集
//数据采集-将表格中的图片资源DataTable表(dt_Image)
DataTable dtImage = GetImageSaveData(sourceData, tb_PIs.__TableName, tb_PIs.RowID, "PI");
this.UpdateCommonFieldsValue(dtImage);
save.Tables.Add(dtImage);
return save;
}
//来源:C/S框架网(www.csframework.com) QQ:23404761
/// <summary>
/// 创建用于保存的临时数据,包含主表、明细表、图片表
/// </summary>
/// <param name="sourceData">当前业务单据数据集</param>
/// <returns></returns>
public override DataSet CreateSaveData(DataSet sourceData)
{
this.DataBindRow.EndEdit();
DataSet save = new DataSet();
save.Tables.Add(this.DataBinder.Copy());//将<主表>添加到数据集
this.UpdateCommonFieldsValue(save.Tables[0]); //更新<主表>公共字段数据
//收集明细表数据
DataTable detail = sourceData.Tables[tb_PIs.__TableName].Copy();
this.UpdateCommonFieldsValue(detail); //更新明细表的公共字段数据
save.Tables.Add(detail); //将<明细表>添加到数据集
//数据采集-将表格中的图片资源DataTable表(dt_Image)
DataTable dtImage = GetImageSaveData(sourceData, tb_PIs.__TableName, tb_PIs.RowID, "PI");
this.UpdateCommonFieldsValue(dtImage);
save.Tables.Add(dtImage);
return save;
}
//来源:C/S框架网(www.csframework.com) QQ:23404761
三、通用GetImageSaveData方法,用于采集图片表
C# Code:
/// <summary>
/// 数据采集表格中的图片资源到DataTable
/// </summary>
/// <param name="dsCurrent">当前业务单据</param>
/// <param name="detailTableName">明细表表名</param>
/// <param name="detailKeyField">明细表主键</param>
/// <param name="docType">单据类型(DocType)</param>
/// <returns></returns>
protected DataTable GetImageSaveData(DataSet dsCurrent, string detailTableName, string detailKeyField, string docType)
{
DataTable dtDetail = dsCurrent.Tables[detailTableName];
DataTable dtImage = dsCurrent.Tables[dt_Image.__TableName].Copy();
foreach (DataRow R in dtDetail.Rows)
{
if (R.RowState == DataRowState.Deleted) continue;
if (R.RowState == DataRowState.Unchanged) continue;
bool exists = dtImage.Select("DocType='" + docType + "' AND ImgID='" + R[detailKeyField].ToString() + "'").Length == 1;
bool isAddImage = R.RowState == DataRowState.Added
/// <summary>
/// 数据采集表格中的图片资源到DataTable
/// </summary>
/// <param name="dsCurrent">当前业务单据</param>
/// <param name="detailTableName">明细表表名</param>
/// <param name="detailKeyField">明细表主键</param>
/// <param name="docType">单据类型(DocType)</param>
/// <returns></returns>
protected DataTable GetImageSaveData(DataSet dsCurrent, string detailTableName, string detailKeyField, string docType)
{
DataTable dtDetail = dsCurrent.Tables[detailTableName];
DataTable dtImage = dsCurrent.Tables[dt_Image.__TableName].Copy();
foreach (DataRow R in dtDetail.Rows)
{
if (R.RowState == DataRowState.Deleted) continue;
if (R.RowState == DataRowState.Unchanged) continue;
bool exists = dtImage.Select("DocType='" + docType + "' AND ImgID='" + R[detailKeyField].ToString() + "'").Length == 1;
bool isAddImage = R.RowState == DataRowState.Added
GetImageSaveData方法代码不全,请下载附件。
四、DAL层CreateSqlGenerator方法添加dt_Image模型
五、界面设计:在表格添加图片组件列(RepositoryItemPictureEdit)
ColumnEdit绑定RepositoryItemPictureEdit组件,重命名:repImgSmall,绑定字段:FieldName=ImgSmall。
Form.Load事件内添加弹出菜单代码:
C# Code:
repImgSmall.PopupMenuShowing += RepImgSmall_PopupMenuShowing;
repImgSmall.PopupMenuShowing += RepImgSmall_PopupMenuShowing;
C# Code:
private void RepImgSmall_PopupMenuShowing(object sender, DevExpress.XtraEditors.Events.PopupMenuShowingEventArgs e)
{
e.PopupMenu.Items.Clear();
UIDataTools.AppendMenu(e.PopupMenu, gvDetail);
}
//来源:C/S框架网(www.csframework.com) QQ:23404761
private void RepImgSmall_PopupMenuShowing(object sender, DevExpress.XtraEditors.Events.PopupMenuShowingEventArgs e)
{
e.PopupMenu.Items.Clear();
UIDataTools.AppendMenu(e.PopupMenu, gvDetail);
}
//来源:C/S框架网(www.csframework.com) QQ:23404761
C# Code:
/// <summary>
/// 添加表格中的图片组件的右键菜单
/// </summary>
/// <param name="menu"></param>
/// <param name="view"></param>
internal static void AppendMenu(DXPopupMenu menu, GridView view)
{
DXMenuItem menuLoadImg = new DXMenuItem("加载图片");
menuLoadImg.Click += new EventHandler(OnLoadImage);
menuLoadImg.Tag = view;
menu.Items.Add(menuLoadImg);
DXMenuItem menuDelImg = new DXMenuItem("删除图片");
menuDelImg.Click += new EventHandler(OnRemoveImage);
menuDelImg.Tag = view;
menu.Items.Add(menuDelImg);
DXMenuItem menuViewImg = new DXMenuItem("查看大图");
menuViewImg.Click += new EventHandler(OnViewImage);
menuViewImg.Tag = view;
menu.Items.Add(menuViewImg);
}
//来源:C/S框架网(www.csframework.com) QQ:23404761
/// <summary>
/// 添加表格中的图片组件的右键菜单
/// </summary>
/// <param name="menu"></param>
/// <param name="view"></param>
internal static void AppendMenu(DXPopupMenu menu, GridView view)
{
DXMenuItem menuLoadImg = new DXMenuItem("加载图片");
menuLoadImg.Click += new EventHandler(OnLoadImage);
menuLoadImg.Tag = view;
menu.Items.Add(menuLoadImg);
DXMenuItem menuDelImg = new DXMenuItem("删除图片");
menuDelImg.Click += new EventHandler(OnRemoveImage);
menuDelImg.Tag = view;
menu.Items.Add(menuDelImg);
DXMenuItem menuViewImg = new DXMenuItem("查看大图");
menuViewImg.Click += new EventHandler(OnViewImage);
menuViewImg.Tag = view;
menu.Items.Add(menuViewImg);
}
//来源:C/S框架网(www.csframework.com) QQ:23404761
UIDataTools类代码不全,请下载附件。
六、点【修改】、【查看】按钮获取数据源的存储过程