系统运行前初始化DBContext
WEB.Config中配置连接串
<add name="DefaultConnection" connectionString="Data Source=192.168.1.58;Initial Catalog=CirclesFinancial;User ID=sa;Password=123456" providerName="System.Data.SqlClient"/>
<add name="LogConnection" connectionString="Data Source=192.168.1.58;Initial Catalog=CirclesFinancial;User ID=sa;Password=123456;Pooling=true;Max Pool Size = 300; Min Pool Size=0; Connection Lifetime = 300;packet size=1000;" providerName="System.Data.SqlClient" />
LogConnection为日志的数据库,会记录访问过程Sql语句的执行,需要log4net配置
log4net.Config.XmlConfigurator.Configure();
//Database配置
ConnectionStringSettings connSet = System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"];
string filePath= Server.MapPath("~/Content/Permission.json");
QQZiFramework.DataBase.DBContext.LoadConfigFromFile(filePath, new DBContextConfig(connSet, "CirclesFinancial.Modals.{0},CirclesFinancial.Modals") { LogSql = 2 });
ConnectionStringSettings logConnSet = System.Configuration.ConfigurationManager.ConnectionStrings["LogConnection"];
QQZiFramework.DataBase.DBContext.LogDBConfig = new DBContextConfig(logConnSet, null);
QQZiFramework.MyHttpUtility.DefaultCertificatePath = Server.MapPath("~/Content");
DBContext.LoadConfigFromFile 方法初始化配置,filepath是一个json文件,里面是访问的sql配置(按需要配置),后面会讲配置文件写法
MyHttpUtility.DefaultCertificatePath 方法,MyHttpUtility是封装的一个httpWebRequest类,get,post,download等方法,添加https的处理,并且对cooike管理的好些,本属性是初始化的证书存放的目录,在某些https访问中会需要证书,项目中不使用的话可不写。
上一篇介绍了DBContext在使用的时候,需要在using的过程中,并且用它来处理数据访问
using (DBContext context = new DBContext(true))
{
context.GetBusiness<RMBDrivers>().SaveSchedule(id, array);
context.Commit();
}
在发生异常的时候会调用context.Dispose()方法,释放连接,如果有事务,会回滚。
需要使用数据访问,需要先了解个概念,数据库的查询是如果被映射到实体的
实体 | 数据表 |
public class DBEntity{ public in ID { get;set; } public string Name{get;set} } | DBEntity表 ID int Name varchar(255) |
要求:
实体必需继承QQZiFramework.DataBase.IDBEntity父类(非接口)
IDBEntity中有一些公用的方法,ParseFromTable,ParseFromTableRow,ToJson等,根据名字能知道用途,重点要讲一下几个自定义属性
DBTableAttribute:写在实体类上,用来定义实体对应的表,IsVirtual:是否是虚拟的表(不存在于数据库中)
[DBTable(TableName = "A0_Order",IsVirtual=False)]
public class Order : IDBEntity
{
}
DBFieldAttribute:写在属性上,用来定义对应的列名,用途(Usage属性,主键,外键,是否包含在默认的查询中等),不定义则默认为同时的表字段
Usage:(PrimaryKey:主键;ForeignKey:外键;MarkDelete:删除状态标记,比如Status;NoField:非表字段,不用于默认查询(虚拟实体除外))
[DBField(Usage=DBFieldUsage.NoField)]
public int BusinessId { get; set; }
[DBField(Usage = DBFieldUsage.ForeignKey,ForeignTable="A0_Area", ForeignTableField="Code")]
public string ParentCode { get; set; }
JsonConverter:被序列化的时候格式化处理类,一般用在日期,有UnixTimeConverter和UnixDateConverter,代理时间和日期
[JsonConverter(typeof(UnixTimeConverter))]
public DateTime PayDate { get; set; }
DefaultValue:初始化实体时候,被默认赋的值,用来做值类型的为空处理, int类型用DefaultNullValue,double,long,decimal:DefaultDoubleValue
[DefaultValue(DefaultNullValue)]
public int Status { get; set; }
所有的表必需要有主键,sqlserver目前必需要用标识列,也就是自增列。实体中需要定义主键,比如
/// <summary>
/// 用户编号
/// </summary>
[DBField(Usage = DBFieldUsage.PrimaryKey)]
public int UserId { get; set; }
QuerySingle<T> | 查询单条数据返回实体 |
QueryMany<T> | 查询多笔数据返回实体集合 |
QueryTree | 查询并返回树型结构实体,需要继承ITreeDBEntity |
QueryTable | 查询语句返回DataTable |
QueryReader | 查询语句返回DataReader |
ExecScalar | 查询单条数据,返回第一行第一列(查询单列) |
ExecuteCommand | 执行语句 |
Exists<T> | 判断是否存在某个条件的记录,对应Sql的exists查询 |
Count<T> | 查询指定条件的记录行 |
Update<T> | 更新指定表的某些列 |
DoSave | 根据实体的值,保存到表中,如果主键有值,则为更新 |
DoDelete<T> | 根据主键删除 |
QuerySingle:查询单条数据返回实体
具有多个重载,列出常用的三个
/// <summary>
/// 查询并返回单个实体
/// </summary>
/// <param name="primarkVal">主键值</param>
/// <param name="throwWhen">没有数据是否抛异常,Null:不抛,空字符串则抛出默认的消息,也可以是传具体的消息内容</param>
public T QuerySingle<T>(string primarkVal, string throwWhen = null) where T : IDBEntity
/// <summary>
/// 查询并返回单个实体
/// </summary>
/// <param name="where">查询条件(动态类)</param>
/// <param name="permission"></param>
/// <param name="queryFilter">查询列(实体属性)过滤,以逗号隔开</param>
/// <param name="throwWhen">没有数据是否抛异常,Null:不抛,空字符串则抛出默认的消息,也可以是传具体的消息内容</param>
/// <returns></returns>
public T QuerySingle<T>(object where, string permission, string queryFilter, string throwWhen) where T : IDBEntity
/// 查询
/// </summary>
/// <param name="permission"配置项名称><pre name="code" class="csharp">配置项名称
</param>/// <param name="primarkVal">主键值</param>/// <param name="queryFilter">查询列(实体属性)过滤,以逗号隔开</param>/// <param name="throwWhen">没有数据是否抛异常,Null:不抛,空字符串则抛出默认的消息,也可以是传具体的消息内容</param>/// <param name="defaultNullValue">值类型属性为空是否标记为DefaultNullValue</param>/// <returns></returns>public T QuerySingle<T>(string permission, int primarkVal, string queryFilter, string throwWhen, bool defaultNullValue) where T : IDBEntity
permission配置项后面讲,where是一个动态类,比如new {ID=10086} ,也可以传复杂的条件,比如 new {name ="like '%吕%'", Status = "> 1"}
QueryMany:查询多笔数据返回实体集合
/// <summary>
/// 查询结果返回List
/// </summary>
/// <param name="sql">查询的语句</param>
/// <returns></returns>
public List<T> QueryMany<T>(string sql) where T : IDBEntity
/// <summary>
/// 查询结果返回List
/// </summary>
/// <param name="where">查询条件(动态类)</param>
/// <param name="queryFilter">查询列(实体属性)过滤,以逗号隔开</param>
/// <returns></returns>
public List<T> QueryMany<T>(object where, string queryFilter = null) where T : IDBEntity
/// <summary>
/// 查询结果返回List
/// </summary>
/// <param name="where">查询条件(动态类)</param>
/// <param name="permission">配置项名称</param>
/// <param name="queryFilter">查询列(实体属性)过滤,以逗号隔开</param>
public List<T> QueryMany<T>(object where, string permission, string queryFilter) where T : IDBEntity
ExecScalar:查询单条数据,返回第一行第一列(查询单列)
/// <summary>
/// 执行语句返回第一行第一列
/// </summary>
/// <param name="sql"></param>
/// <returns>第一行第一列值,如果是空则为DBNull.Value</returns>
public object ExecScalar(string sql)
/// <summary>
/// 查询某个字段的值
/// </summary>
/// <param name="fieldName">字段名</param>
/// <param name="primaryKey">主键值</param>
/// <returns>如果字段为空则返回null(注意:不是DBNull.Value)</returns>
public object ExecScalar<T>(string fieldName, int primaryKey)
/// <summary>
/// 查询某个字段的值
/// </summary>
/// <param name="fieldName">字段名</param>
/// <param name="primaryKey">主键值</param>
/// <returns>如果字段为空则返回null(注意:不是DBNull.Value)</returns>
public object ExecScalar<T>(string fieldName, object where, string throwNull)
DoSave:根据实体的值,保存到表中,如果主键有值,则为更新
/// <summary>
/// 保存对象到表,可以配置文件中设定不允许修改的列NotAllow
/// </summary>
/// <param name="permission">保存配置项</param>
/// <param name="entity">要保存的实体对象</param>
public int DoSave(string permission, IDBEntity entity)
/// <summary>
/// 保存对象到表
/// </summary>
/// <param name="entity">要保存的实体对象</param>
public int DoSave(IDBEntity entity)
其它:
/// <summary>
/// 查询是否有指定的记录
/// </summary>
/// <param name="permission">查询配置项</param>
/// <param name="entityName">实体名</param>
/// <param name="where">条件动态类</param>
/// <returns></returns>
public bool Exists(string permission, string entityName, object where)
/// <summary>
/// 查询是否有指定的记录
/// </summary>
/// <param name="where">条件动态类</param>
/// <returns></returns>
public bool Exists<T>(object where) where T : IDBEntity
/// <summary>
/// 查询记录数
/// </summary>
/// <param name="entityName"></param>
/// <param name="where">条件动态类</param>
/// <returns></returns>
public int Count<T>(object where) where T : IDBEntity
/// <summary>
/// 更新单个列
/// </summary>
/// <param name="PropertyName">实体属性</param>
/// <param name="value">值</param>
/// <returns>受影响行数</returns>
public int Update<T>(string PropertyName, object value, int primaryKey) where T : IDBEntity
/// <summary>
/// 更新单个列
/// </summary>
/// <param name="columnAndValues">要更新的内容,动态类,比如{Name="吕存库",Sex=1}</param>
/// <param name="primaryKey">主键值</param>
/// <returns>受影响行数</returns>
public int Update<T>(object columnAndValues, int primaryKey) where T : IDBEntity
举例:
public const string User_NoFound_ErrorMsg = "用户不存在!";
User user = Context.QuerySingle<User>(null, id, "Name", User_NoFound_ErrorMsg);//也可以用*号取出所有的字段
user.Name="吕存库";
Context.DoSave(user);//会更新整个实体,如果属性有值的话
Context.ExecuteCommand("update A0_Users set Name='"+user.Name+"' where userId="+ user.UserId);
//创建新用户
User newUser =new User(){Name="新用户",Mobile="17097913883"};
Context.DoSave(newUser);
//判断用户是否存在:
if(Context.Exists<User>(new{Mobile="17097913883"})){ Console.WriteLine("用户存在"); }
//获取UserId为1的用户的Name
Context.ExecScalar<User>("Name",1);
//查询所有手机号为170开头的用户列表
Context.QueryMany<User>(new {Mobile = "like '170%'"},null,null)
GetSystemParam:获取自己在数据库中的参数配置
需要在数据库中有A1_Config表
CREATE TABLE [dbo].[A1_Configs] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[ParamName] VARCHAR (64) NOT NULL,
[ParamValue] VARCHAR (256) NULL,
[Remark] VARCHAR (64) NULL,
CONSTRAINT [PK_A1_Configs] PRIMARY KEY CLUSTERED ([Id] ASC)
);
比如:
int ApplyDayBefore = Context.GetSystemParam<int>("ApplyDayBefore", true);//true代表不存在配置是否抛出异常
HasLock:是否存在访问锁定,没有则加锁,有则返回true,需要自己去处理有锁的逻辑,用于异常多次执行的判断,比如银行或者其它支付机构的回调,可能有多次。我们只处理第一次成功的情况。
只按传入的Key做判断,注意唯一性,可以用模块名称+主键的方式
Utility.LogMessage("缴费回调,trxId:" + trxId + ",orderId:" + orderStr);
using (DBContext context = new DBContext())
{
if (context.HasLock("PayFinish" + orderStr)) {
Utility.LogMessage("已处理过,不执行!");
return;
}
......
}
StrictModel:严格模式
如果设置DBContext的StrictModel为True,则必需要指定Permission,并且操作的列并且在实体中存在,或者在json配置中存在,比如上面的where条件,mobile ="like '170%'",严格模式下就不能使用,除非有配置