FluentData -Micro ORM with a fluent API that makes it simple to query a database 【MYSQL】
官方地址:http://fluentdata.codeplex.com/documentation
MYSQL:
- MySQL through the MySQL Connector .NET driver.
连接字符串: Server=127.0.0.1;Database=testDB;Uid=root;Pwd=123456; <system.data>
<DbProviderFactories>
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory,MySql.Data" />
</DbProviderFactories>
</system.data>
Table of Contents
Contents
Getting started
Requirements
- .NET 4.0.
Supported databases
- MS SQL Server using the native .NET driver.
- MS SQL Azure using the native .NET driver.
- MS Access using the native .NET driver.
- MS SQL Server Compact 4.0 through the Microsoft SQL Server Compact 4.0 driver.
- Oracle through the ODP.NET driver.
- MySQL through the MySQL Connector .NET driver.
- SQLite through the SQLite ADO.NET Data Provider.
- PostgreSql through the Npgsql provider.
- IBM DB2
Installation
If you are using NuGet:
- Search for FluentData and click Install.
If you are not using NuGet:
- Download the zip with the binary files.
- Extract it, and copy the files to your solution or project folder.
- Add a project reference to FluentData.dll.
Core concepts
DbContext
This class is the starting point for working with FluentData. It has properties for defining configurations such as the connection string to the database, and operations for querying the database.
DbCommand
This is the class that is responsible for performing the actual query against the database.
Events
The DbContext class has support for the following events:
- OnConnectionClosed
- OnConnectionOpened
- OnConnectionOpening
- OnError
- OnExecuted
- OnExecuting
By using any of these then you can for instance write to the log if an error has occurred or when a query has been executed.
Builders
A builder provides a nice fluent API for generating SQL for insert, update and delete queries.
Mapping
FluentData can automap the result from a SQL query to either a dynamic type (new in .NET 4.0) or to your own .NET entity type (POCO - Plain Old CLR Object) by using the following convention:
Automap to an entity type:
- If the field name does not contain an underscore ("_") then it will try to try to automap to a property with the same name. For instance a field named "Name" would be automapped to a property also named "Name".
- If a field name does contain an underscore ("") then it will try to map to a nested property. For instance a field named "CategoryName" would be automapped to the property "Category.Name".
If there is a mismatch between the fields in the database and in the entity type then the alias keyword in SQL can be used or you can create your own mapping method. Check the mapping section below for code samples.
Automap to a dynamic type:
- For dynamic types every field will be automapped to a property with the same name. For instance the field name Name would be automapped to the Name property.
When should you dispose?
- DbContext must be disposed if you have enabled UseTransaction or UseSharedConnection.
- DbCommand must be disposed if you have enabled UseMultiResult (or MultiResultSql).
- StoredProcedureBuilder must be disposed if you have enabled UseMultiResult.
In all the other cases dispose will be handled automatically by FluentData. This means that a database connection is opened just before a query is executed and closed just after the execution has been completed.
Code samples
Create and initialize a DbContext
The connection string on the DbContext class can be initialized either by giving the connection string name in the *.config file or by sending in the entire connection string.
Important configurations
- IgnoreIfAutoMapFails - Calling this prevents automapper from throwing an exception if a column cannot be mapped to a corresponding property due to a name mismatch.
Create and initialize a DbContext
The DbContext can be initialized by either calling ConnectionStringName which will read the connection string from the *.config file:
public IDbContext Context()
{
return new DbContext().ConnectionStringName("MyDatabase",
new SqlServerProvider());
}
or by calling the ConnectionString method to set the connection string explicitly:
public IDbContext Context()
{
return new DbContext().ConnectionString(
"Server=MyServerAddress;Database=MyDatabase;Trusted_Connection=True;", new SqlServerProvider());
}
Providers
If you want to work against another database than SqlServer then simply replace the new SqlServerProvider() in the sample code above with any of the following:
AccessProvider, DB2Provider, OracleProvider, MySqlProvider, PostgreSqlProvider, SqliteProvider, SqlServerCompact, SqlAzureProvider, SqlServerProvider.
Query for a list of items
Return a list of dynamic objects (new in .NET 4.0):
List<dynamic> products = Context.Sql("select * from Product").QueryMany<dynamic>();
Return a list of strongly typed objects:
List<Product> products = Context.Sql("select * from Product").QueryMany<Product>();
Return a list of strongly typed objects in a custom collection:
ProductionCollection products = Context.Sql("select * from Product").QueryMany<Product, ProductionCollection>();
Return a DataTable:
See Query for a single item.
Query for a single item
Return as a dynamic object:
dynamic product = Context.Sql(@"select * from Product
where ProductId = 1").QuerySingle<dynamic>();
Return as a strongly typed object:
Product product = Context.Sql(@"select * from Product
where ProductId = 1").QuerySingle<Product>();
Return as a DataTable:
DataTable products = Context.Sql("select * from Product").QuerySingle<DataTable>();
Both QueryMany<DataTable> and QuerySingle<DataTable> can be called to return a DataTable, but since QueryMany returns a List<DataTable> then it's more convenient to call QuerySingle which returns just DataTable. Eventhough the method is called QuerySingle then multiple rows will still be returned as part of the DataTable.
Query for a scalar value
int numberOfProducts = Context.Sql(@"select count(*)
from Product").QuerySingle<int>();
Query for a list of scalar values
List<int> productIds = Context.Sql(@"select ProductId
from Product").QueryMany<int>();
Parameters
Indexed parameters:
dynamic products = Context.Sql(@"select * from Product
where ProductId = @0 or ProductId = @1", 1, 2).QueryMany<dynamic>();
or:
dynamic products = Context.Sql(@"select * from Product
where ProductId = @0 or ProductId = @1")
.Parameters(1, 2).QueryMany<dynamic>();
Named parameters:
dynamic products = Context.Sql(@"select * from Product
where ProductId = @ProductId1 or ProductId = @ProductId2")
.Parameter("ProductId1", 1)
.Parameter("ProductId2", 2)
.QueryMany<dynamic>();
Output parameter:
var command = Context.Sql(@"select @ProductName = Name from Product
where ProductId=1")
.ParameterOut("ProductName", DataTypes.String, 100);
command.Execute(); string productName = command.ParameterValue<string>("ProductName");
List of parameters - in operator:
List<int> ids = new List<int>() { 1, 2, 3, 4 };
dynamic products = Context.Sql(@"select * from Product
where ProductId in(@0)", ids).QueryMany<dynamic>();
Mapping
Automapping - 1:1 match between the database and the .NET object:
List<Product> products = Context.Sql(@"select *
from Product")
.QueryMany<Product>();
Automap to a custom collection:
ProductionCollection products = Context.Sql("select * from Product").QueryMany<Product, ProductionCollection>();
Automapping - Mismatch between the database and the .NET object, use the alias keyword in SQL:
Weakly typed:
List<Product> products = Context.Sql(@"select p.*,
c.CategoryId as Category_CategoryId,
c.Name as Category_Name
from Product p
inner join Category c on p.CategoryId = c.CategoryId")
.QueryMany<Product>();
Here the p.* which is ProductId and Name would be automapped to the properties Product.Name and Product.ProductId, and Category_CategoryId and Category_Name would be automapped to Product.Category.CategoryId and Product.Category.Name.
Custom mapping using dynamic:
List<Product> products = Context.Sql(@"select * from Product")
.QueryMany<Product>(Custom_mapper_using_dynamic); public void Custom_mapper_using_dynamic(Product product, dynamic row)
{
product.ProductId = row.ProductId;
product.Name = row.Name;
}
Custom mapping using a datareader:
List<Product> products = Context.Sql(@"select * from Product")
.QueryMany<Product>(Custom_mapper_using_datareader); public void Custom_mapper_using_datareader(Product product, IDataReader row)
{
product.ProductId = row.GetInt32("ProductId");
product.Name = row.GetString("Name");
}
Or if you have a complex entity type where you need to control how it is created then the QueryComplexMany/QueryComplexSingle can be used:
var products = new List<Product>();
Context.Sql("select * from Product").QueryComplexMany<Product>(products, MapComplexProduct); private void MapComplexProduct(IList<Product> products, IDataReader reader)
{
var product = new Product();
product.ProductId = reader.GetInt32("ProductId");
product.Name = reader.GetString("Name");
products.Add(product);
}
Multiple result sets
FluentData supports multiple resultsets. This allows you to do multiple queries in a single database call. When this feature is used it's important to wrap the code inside a using statement as shown below in order to make sure that the database connection is closed.
using (var command = Context.MultiResultSql)
{
List<Category> categories = command.Sql(
@"select * from Category;
select * from Product;").QueryMany<Category>(); List<Product> products = command.QueryMany<Product>();
}
The first time the Query method is called it does a single query against the database. The second time the Query is called, FluentData already knows that it's running in a multiple result set mode, so it reuses the data retrieved from the first query.
Select data and Paging
A select builder exists to make selecting data and paging easy:
List<Product> products = Context.Select<Product>("p.*, c.Name as Category_Name")
.From(@"Product p
inner join Category c on c.CategoryId = p.CategoryId")
.Where("p.ProductId > 0 and p.Name is not null")
.OrderBy("p.Name")
.Paging(1, 10).QueryMany();
By calling Paging(1, 10) then the first 10 products will be returned.
Insert data
Using SQL:
int productId = Context.Sql(@"insert into Product(Name, CategoryId)
values(@0, @1);")
.Parameters("The Warren Buffet Way", 1)
.ExecuteReturnLastId<int>();
Using a builder:
int productId = Context.Insert("Product")
.Column("Name", "The Warren Buffet Way")
.Column("CategoryId", 1)
.ExecuteReturnLastId<int>();
Using a builder with automapping:
Product product = new Product();
product.Name = "The Warren Buffet Way";
product.CategoryId = 1; product.ProductId = Context.Insert<Product>("Product", product)
.AutoMap(x => x.ProductId)
.ExecuteReturnLastId<int>();
We send in ProductId to the AutoMap method to get AutoMap to ignore and not map the ProductId since this property is an identity field where the value is generated in the database.
Update data
Using SQL:
int rowsAffected = Context.Sql(@"update Product set Name = @0
where ProductId = @1")
.Parameters("The Warren Buffet Way", 1)
.Execute();
Using a builder:
int rowsAffected = Context.Update("Product")
.Column("Name", "The Warren Buffet Way")
.Where("ProductId", 1)
.Execute();
Using a builder with automapping:
Product product = Context.Sql(@"select * from Product
where ProductId = 1")
.QuerySingle<Product>();
product.Name = "The Warren Buffet Way"; int rowsAffected = Context.Update<Product>("Product", product)
.AutoMap(x => x.ProductId)
.Where(x => x.ProductId)
.Execute();
We send in ProductId to the AutoMap method to get AutoMap to ignore and not map the ProductId since this is the identity field that should not get updated.
Insert and update - common Fill method
var product = new Product();
product.Name = "The Warren Buffet Way";
product.CategoryId = 1; var insertBuilder = Context.Insert<Product>("Product", product).Fill(FillBuilder); var updateBuilder = Context.Update<Product>("Product", product).Fill(FillBuilder); public void FillBuilder(IInsertUpdateBuilder<Product> builder)
{
builder.Column(x => x.Name);
builder.Column(x => x.CategoryId);
}
Delete data
Using SQL:
int rowsAffected = Context.Sql(@"delete from Product
where ProductId = 1")
.Execute();
Using a builder:
int rowsAffected = Context.Delete("Product")
.Where("ProductId", 1)
.Execute();
Stored procedure
Using SQL:
var rowsAffected = Context.Sql("ProductUpdate")
.CommandType(DbCommandTypes.StoredProcedure)
.Parameter("ProductId", 1)
.Parameter("Name", "The Warren Buffet Way")
.Execute();
Using a builder:
var rowsAffected = Context.StoredProcedure("ProductUpdate")
.Parameter("Name", "The Warren Buffet Way")
.Parameter("ProductId", 1).Execute();
Using a builder with automapping:
var product = Context.Sql("select * from Product where ProductId = 1")
.QuerySingle<Product>();
product.Name = "The Warren Buffet Way";
var rowsAffected = Context.StoredProcedure<Product>("ProductUpdate", product)
.AutoMap(x => x.CategoryId).Execute();
Using a builder with automapping and expressions:
var product = Context.Sql("select * from Product where ProductId = 1")
.QuerySingle<Product>();
product.Name = "The Warren Buffet Way";
var rowsAffected = Context.StoredProcedure<Product>("ProductUpdate", product)
.Parameter(x => x.ProductId)
.Parameter(x => x.Name).Execute();
Transactions
FluentData supports transactions. When you use transactions its important to wrap the code inside a using statement to make sure that the database connection is closed. By default, if any exception occur or if Commit is not called then Rollback will automatically be called.
using (var context = Context.UseTransaction(true))
{
context.Sql("update Product set Name = @0 where ProductId = @1")
.Parameters("The Warren Buffet Way", 1)
.Execute(); context.Sql("update Product set Name = @0 where ProductId = @1")
.Parameters("Bill Gates Bio", 2)
.Execute(); context.Commit();
}
Entity factory
The entity factory is responsible for creating object instances during automapping. If you have some complex business objects that require special actions during creation, you can create your own custom entity factory:
List<Product> products = Context.EntityFactory(new CustomEntityFactory())
.Sql("select * from Product")
.QueryMany<Product>(); public class CustomEntityFactory : IEntityFactory
{
public virtual object Resolve(Type type)
{
return Activator.CreateInstance(type);
}
}
Last edited Jun 30, 2013 at 7:32 PM by kindblad, version 4
FluentData -Micro ORM with a fluent API that makes it simple to query a database 【MYSQL】的更多相关文章
- FluentData -Micro ORM with a fluent API that makes it simple to query a database
Code samples Create and initialize a DbContextThe connection string on the DbContext class can be in ...
- 17.翻译系列:将Fluent API的配置迁移到单独的类中【EF 6 Code-First系列】
原文链接:https://www.entityframeworktutorial.net/code-first/move-configurations-to-seperate-class-in-cod ...
- How to Use HTML5 FUll Screen API(如何使用HTML5全屏接口) 【精】
原文链接:http://www.sitepoint.com/use-html5-full-screen-api/ 如果你不太喜欢变化太快的东西,那么web开发可能不适合你.我曾在2012年末有写过Fu ...
- Fluent批处理之--windows下多个任务的计算 【转载】
转载自http://jingcao830828.blog.163.com/blog/static/10320833620103633624506/ 1.同维多任务的连续计算 对于工程应用来说,计算精度 ...
- fluent当中的梯度宏和VOF梯度的获取【转载】
1 FLUENT变量梯度宏 C_R_G C_P_G C_U_G C_V_G C_W_G C_T_G C_H_G C_YI_G C_R_RG C_P_RG C_U_RG C_V_RG C_W_RG C_ ...
- EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射
I.EF里的默认映射 上篇文章演示的通过定义实体类就可以自动生成数据库,并且EF自动设置了数据库的主键.外键以及表名和字段的类型等,这就是EF里的默认映射.具体分为: 数据库映射:Code First ...
- EF——默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射 02 (转)
EF里的默认映射以及如何使用Data Annotations和Fluent API配置数据库的映射 I.EF里的默认映射 上篇文章演示的通过定义实体类就可以自动生成数据库,并且EF自动设置了数据库 ...
- 10.翻译系列:EF 6中的Fluent API配置【EF 6 Code-First系列】
原文链接:https://www.entityframeworktutorial.net/code-first/fluent-api-in-code-first.aspx EF 6 Code-Firs ...
- 10.2.翻译系列:使用Fluent API进行属性映射【EF 6 Code-First】
原文链接:https://www.entityframeworktutorial.net/code-first/configure-property-mappings-using-fluent-api ...
随机推荐
- MVC实战之排球计分(八)——软件制作总结
此系列博客目的是制作一款排球计分程序.这系列博客将讲述此软件的 各个功能的设计与实现.到这篇博客,此系列博客就算是结束了. 在最后的这篇博客里 我们来做一些总结. 一,制作此程序,我们使用的是MVC框 ...
- 中国历史人物传记数据库 CBDB 若干表简介
''' 推荐使用SQLite版本的CBDB数据库 推荐使用SQlite Studio进行数据库的操作 免费,可视化操作,轻量级应用,无需配置,学习扩展性好,非常适合广大历史系学生. ''' 一 人物基 ...
- [poj P1475] Pushing Boxes
[poj P1475] Pushing Boxes Time Limit: 2000MS Memory Limit: 131072K Special Judge Description Ima ...
- linux 安装配置zookeeper
1.什么是zookeeper ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用 ...
- 福大软工 · 第十一次作业 - Alpha 事后诸葛亮(团队)
福大软工·第十一次作业-Alpha事后诸葛亮 组长博客链接 本次作业博客链接 项目Postmortem 模板 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描 ...
- Nginx源代码安装
1.确认系统平台及版本 [root@Trial html]# uname -r 2.6.32-696.6.3.el6.x86_64 [root@Trial html]# cat /etc/redhat ...
- oracle开发错误
先展示一个错误写法 public static String printGg_bysly0List() {// 外网 TransManager tm = new TransManager(); try ...
- MFC无闪烁隐藏窗口
今天需要用到将窗口的程序隐藏,但是如果在OnInitDialog()中,直接写: ShowWindow(SW_HIDE); 是无效的,因为这本身就是个初始化窗口函数.也就是说,窗口在并没有显示出来的时 ...
- C# 网络通信功能 同步数据交互开发
前言 本文将使用一个Nuget公开的组件技术来实现一对多的数据通信功能,提供了一些简单的API,来方便的向服务器进行数据请求. 在visual studio 中的Nuget管理器中可以下载安装,也可以 ...
- c语言笔记3运算符与表达式
运算符与表达式 知识点一 操作数:参与运算的具体对象. 运算符:指明了对操作数进行的某项运算. 表达式:表示一个求值得规则.它由变量.常量.运算符和函数.括号按一定规则组成. 书写表达式的细节:1,运 ...