FluentData -Micro ORM with a fluent API that makes it simple to query a database

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 };
//becareful here,don‘t leave any whitespace around in(...) syntax.
dynamic products = Context.Sql(@"select * from Product
			where ProductId in(@0)", ids).QueryMany<dynamic>();

like operator:

string cens = "%abc%";
Context.Sql("select * from Product where ProductName like @0",cens);

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.

IgnoreIfAutoMapFails
When read from database,If some data columns not mappinged with entity class,by default ,will throw exception.

if you want ignore the exception, or the property not used for map data table,then you can use the IgnoreIfAutoMapFails(true),this will ignore the exception when read mapping error.

context.IgnoreIfAutoMapFails(true);

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 Mar 2, 2015 at 4:36 AM by kindblad, version 52

url:  http://fluentdata.codeplex.com/documentation#Events

时间: 2024-10-08 23:32:52

FluentData -Micro ORM with a fluent API that makes it simple to query a database的相关文章

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=jnex;<system.data> <DbProviderFactories> <add name="MySQL Data Provider" i

ORM系列之二:EF(4) 约定、注释、Fluent API

目录 1.前言 2.约定 2.1 主键约定 2.2 关系约定 2.3 复杂类型约定 3.数据注释 3.1 主键 3.2 必需 3.3 MaxLength和MinLength 3.4 NotMapped 3.5 复杂属性 3.6 ConcurrencyCheck 4.Fluent API 5.总结 前言 在之前的Code First示例中,我们编写好代码直接运行,就自动会自定创建数据库,并且根据定义好的类创建了对应的表,更加神奇的时候竟然还能自动创建主键.外键等等.这是如何实现的呢?如果我们想指定

What would be the closest equivalent in Java to a Micro ORM such as Dapper, PetaPoco, Massive or CodingHorror?

Java Micro ORM equivalent [closed] Ask Question up vote 51 down vote favorite 21 What would be the closest equivalent in Java to a Micro ORM such as Dapper, PetaPoco, Massive or CodingHorror? java subsonic dapper petapoco massive shareimprove this qu

SimpleReact: 基于Java 8简单的FRP Fluent API

SimpleReact来自AOL的一个小型的支持并发的库包,其直接基于Java 8的CompletableFuture, JDK函数接口和Streams API构建,它的Fluent API能够提供解决90%的Reactive使用场景,重要的是没有带入任何复杂性.可以实现Functional Reactive Programming范式(简称:FRP,函数式响应编程) 使用SimpleReact能够方便扩展微服务,它能用于管理微服务的远程调用,能够应付高并发大型高性能平台的要求. 使用Simpl

使用Fluent API进行实体映射【Code-First系列】

现在,我们来学习怎么使用Fluent API来配置实体. 一.配置默认的数据表Schema Student实体 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF4 { public class Student { public int StudentID { get; set; } publ

Fluent API in Code-First【Code-First系列】

在前面的章节中,我们已经看到了各种不同的数据注解特性.现在我们来学习一下Fluent API. Fluent API是另外一种配置领域类的方式,它提供了更多的配置相比数据注解特性. Mappings[映射] To Database[转成数据库] Model-wide Mapping[模型映射] Set default Schema[设置默认的Schema] Set Custom Convetions[自定义约定] Entity Mapping[实体映射] To Single or Multipl

关于CodeFirst异常:无法确定类型&#39;XXX&#39;和类型‘YYY’之间的关联的主体端,必须使用关系 Fluent API 或数据注释显式配置此关联的主体端。

此错误的原因是,你配置两个实体间的关系为一对一 然而我认为的一对一关系是,两者之间必须存在一个主体, 也就是说,你不能表1的外键是表2的主键并且表1的主键是表2的外键, 这样不符合数据库式吧? 我想多数人犯这个错误是无意的,并不是想表1的外键是表2的主键并且表1的主键是表2的外键, 怎么改呢?确定主体! 主体就是你要把其他实体的主键存进来的实体. 把非实体的导航属性删除就ok了. 关于CodeFirst异常:无法确定类型'XXX'和类型'YYY'之间的关联的主体端,必须使用关系 Fluent A

Code First 中 Fluent API 的作用

Code First 的使用:http://www.cnblogs.com/sword-successful/archive/2012/12/31/2840391.html(写的很明白) Fluent API 的用法:https://msdn.microsoft.com/zh-cn/data/jj591617.aspx:http://www.dozer.cc/2012/09/entity-framework-code-first-configuring-property/

一起学ASP.NET Core 2.0学习笔记(二): ef core2.0 及mysql provider 、Fluent API相关配置及迁移

不得不说微软的技术迭代还是很快的,上了微软的船就得跟着她走下去,前文一起学ASP.NET Core 2.0学习笔记(一): CentOS下 .net core2 sdk nginx.supervisor.mysql环境搭建搭建好了.net core linux的相关环境,今天就来说说ef core相关的配置及迁移: 简介: Entity Framework(以下简称EF) 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案,EF Core是Entity