Smark.Data是一款开源轻量级的数据访问组件,它能提供极其方便高效的数据访问操作;灵活的条件操作方式和数据获取描述是现有很多数据库访问组件所不具备.以下对组件的使用进行简单的介绍.
项目地址:http://smark.codeplex.com/
blog: http://www.cnblogs.com/smark http://henryfan.net
设置访问数据类型和连接信息
在操作数据库这前设置相关信息是必须的,组件可以通过以下代码设置数据库访问类型和连接信息(也可以通过配置文件进行设置).
|
1
2
3
|
string dbpath = @"Data Source=..\\..\\..\\lib\\northwind.db;Pooling=true;FailIfMissing=false;";
DBContext.SetConnectionDriver<SqliteDriver>(ConnectionType.Context1);DBContext.SetConnectionString(ConnectionType.Context1, dbpath); |
组件可以设置多个数据访问类型,通过ConnectionType来设置相关数据库访问类型,在操作数据如果不指定数据库,则使会使第Context1个配置的数据库类型。
制定实体类
和大部分数据访问组件一样,在进行数据库操作之前要制定一个实体类(如果直接用SQL进行操作不需要,组件也支持直接SQL操作)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
[Table("customers")]
public interface ICustomer
{
[ID]
string CustomerID { get; set; }
[Column]
string CompanyName { get; set; }
[Column]
string ContactName { get; set; }
[Column]
string Address { get; set; }
[Column]
string City { get; set; }
[Column]
string Region { get; set; }
[Column]
string PostalCode { get; set; }
[Column]
string Country { get; set; }
[Column]
string Phone { get; set; }
[Column]
string Fax { get; set; }
}
|
以上实体描述是基于Smark.Data.I2MGenerator插件的基础上的,该插件所提供的功能就是针对以上接收文件自动生成需要的实体类;如果人工手动去编写一个实体类是相对比较复杂的.
针对上面的实体类进行一个简单的数据操作,查询某个国家和城市的客户.
|
1
2
|
Expression exp = Customer.country == "USA" & Customer.city == "OR";
var items = exp.List<Customer>(); |
如果你认为定义一个变量麻烦也可以这样
|
1
|
var items=(Customer.country == "USA" & Customer.city == "OR").List<Customer>();
|
基础增,删,改
数据增加
|
1
2
3
4
5
|
Employee emp = new Employee();
emp.FirstName = "fan";
emp.LastName = "henry";
emp.City = "guangzhou";
DBContext.Save(emp); |
组件会根据设置成员值的情况来更新相关字段,当没有更改值的属性并不会生成相关SQL添加到数据库中。
数据删除
|
1
2
|
emp = DBContext.Load<Employee>(3);DBContext.Delete(emp); |
以上方法是删除一个已获取的对象,实在应用很多时候是针对一个条件删除,后面条件表达式描述会讲术.
数据修改
|
1
2
3
|
emp = DBContext.Load<Employee>(3);emp.Notes = "test,remark";
DBContext.Save(emp); |
以上修改一个已获取的对象,实在应用很多时候是针对一个条件修改,后面条件表达式描述会讲术
条件表达式
简单数据查询
|
1
2
|
Expression exp = Customer.country == "USA" & Customer.city == "OR";
var items = exp.List<Customer>(); |
动态组合查询
|
1
2
3
4
5
6
7
8
9
10
|
Expression exp = new Expression();
if (string.IsNullOrEmpty(employeeid))
exp &= Order.employeeID == employeeid;
if (string.IsNullOrEmpty(customerid))
exp &= Order.customerID == customerid;
if (from != null)
exp &= Order.orderDate > from;
if(to !=null)
exp &= Order.orderDate <to;
var items = exp.List<Order>(); |
条件复用
|
1
2
3
4
5
|
exp = Employee.employeeID == 6;var employees = exp.List<Employee>();var orders = exp.List<Order>();exp.Delete<Employee>();exp.Delete<Order>(); |
数据修改
|
1
|
(Customer.country == "USA").Edit<Customer>(d => { d.City = "abs"; });
|
数据删除
|
1
|
(Customer.country == new[] { "USA", "UK" }).Delete<Customer>();
|
数据统计
|
1
2
|
exp.Count<Customer>();exp.Sum<double, Product>(Product.unitPrice.Name);
|
视图,统计实体定义
在应用中查询返回一个简化的字段列表或一个分组汇总的数据列表是比较普遍的需求,组件针对这种情况并没有以组件列表或一个匿名类列表的方式返回,而是通过类似于表实体的方式制定一个查询实体。查询实体的作用除提供一个强类型查询对象返回外,还能提供有效的查询描述;很大程序上简化了在应用时查询代码的编写。
单一表视图实体描述,应用时并不是什么时候都需要获了一个表的所有字段,有很多时候只需要一部分就行了。可以针对获取这部分字段信息制定一个查询实体。
|
1
2
3
4
5
6
7
8
9
10
|
[Table("employees")]
public interface IEmployeeView
{
[ID]
string EmployeeID { get; set; }
[Column]
string FirstName { get; set; }
[Column]
string LastName { get; set; }
}
|
|
1
2
|
Expression exp = new Expression();
var empviews = exp.List<EmployeeView>();
|
表关联查询实体
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
[Table("customers inner join orders on customers.customerid=orders.customerid")]
public interface ICustomerOrders
{
[Column]
string CompanyName { get; set; }
[Column]
string ContactName { get; set; }
[Column]
[DateTimToLong]
DateTime OrderDate { get; set; }
[Column]
[DateTimToLong]
DateTime RequiredDate { get; set; }
[Column]
string ShipName { get; set; }
[Column]
string ShipAddress { get; set; }
[Column]
string ShipCity { get; set; }
[Column]
string ShipRegion { get; set; }
[Column]
string ShipPostalCode { get; set; }
[Column]
string ShipCountry { get; set; }
}
|
|
1
2
|
Expression exp = new Expression();
var empviews = exp.List<CustomerOrders>(); |
数据汇总统计实体,数据统计需要制定相关统计对象,以下是统计各城市客户订单数量
|
1
2
3
4
5
6
7
8
9
10
|
[Table("customers inner join orders on customers.customerid=orders.customerid")]
public interface ICustOrderGroupByCity
{
[Column]
string Country { get; set; }
[Column]
string City { get; set; }
[Count]
int Count { get; set; }
}
|
|
1
2
|
Expression exp = new Expression();
var empviews = exp.List<CustOrderGroupByCity>(); |
事务处理
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
Expression exp = new Expression();
exp = Employee.employeeID == 5;using (IConnectinContext cc = DBContext.Context1)
{ cc.BeginTransaction();
exp.Delete<Order>();
exp.Delete<Employee>();
cc.Commit();
}DBContext.TransactionExecute(c => { exp.Delete<Order>();
exp.Delete<Employee>();
}); |
运态更改实体对应的表
似乎在很多实体数据访问组件中,实体类型和表都是一一对应的;但总有些应用是根据时间段来数据分表存储,如Order2010,Order2012按年,月或一些规则划分。如果实体和表一表对应的话就比较麻烦,因为有些表是系统运行一段时间后生成的,并不是原来就有,这样会导致实体无法访问后期创建的表信息。组件提供运行动态更改实体对应表关系,方便地解决这种问题出现。
|
1
2
3
4
|
using (IDisposable ct = DBContext.ChangeTable<Order>("ordertbl1"))
{ items = (Order.customerID == Customer.customerID[Customer.country == "UK"]).List<Order>();
} |
只需要调用DBContext.ChangeTable方法即可更改实体对应的表,当该对象释放后实体对应的表会还原。
支持那些数据?
组件内置支持MSSQ,MYSQL,ACCESS,SQLITE,ORACLE等数据库,使用者可以根据需要扩展对SQL92支持的数据访问设备。
实现对sqlite支持的类型
|
1
2
3
4
5
6
7
8
|
public class SqliteDriver : Smark.Data.DriverTemplate<
System.Data.SQLite.SQLiteConnection,
System.Data.SQLite.SQLiteCommand,
System.Data.SQLite.SQLiteDataAdapter,
System.Data.SQLite.SQLiteParameter,
Smark.Data.SqlitBuilder>
{} |