欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

轻量ORM-SqlRepoEx (十五)最佳实践之数据映射(Map)

程序员文章站 2022-06-30 13:30:24
SqlRepoEx是 .Net平台下兼容.NET Standard 2.0人一个轻型的ORM。解决了Lambda转Sql语句这一难题,SqlRepoEx使用的是Lambda表达式,所以,对c#程序员来说,是非常简单的,其语法特点与Linq to Sql极为相似。不仅实现了完整的Select、Inse... ......

简介:sqlrepoex是 .net平台下兼容.net standard 2.0人一个轻型的orm。解决了lambda转sql语句这一难题,sqlrepoex使用的是lambda表达式,所以,对c#程序员来说,是非常简单的,其语法特点与linq to sql极为相似。不仅实现了完整的select、insert、update、delete等语句解析器,同时,也实现了select、where、order by等子句,这些语句与子句均支持导出sql语句,使得拼接复杂场景sql语句变得轻松,sqlrepoex很快其原生数据访问与dapper不相上下,sqlrepoex本身支持sql server与mysql方言,同时通过sqlrepoex.normal支持非方言sql。sqlrepoex没侵入性,仅通过简单的几个特性,就能让类与数据库关联起来;

 

*本系列以静态工厂为例;

*数据来源于northwind数据库;

*完整的代码见 https://github.com/azthinker/sqlrepoex2.0startguid  https://gitee.com/azthinker/sqlrepoex2.0startguid

 

1、从 sqlrepoex 2.2.1 起,标识数据据字段的特性标识改为使用system.componentmodel.dataannotations中的声明,降低使用难度,当然 sqlrepoex 中自定义的特性依然是支持的。

2、只有以类属性定义的,才能作为数据字段使用, sqlrepoex 只反身属性。

3、sqlrepoex 不使用xml文件来映射关系

 

一、表名

1、如果不使用任何特性, sqlrepoex会将当前类名当成数名。

如:

 public sealed class azproducts

    {

    ...

    }

    会返回形如  select ...  from azproducts

    显然,azcategories在数据库中不存在,当然,如果类名与数据库中对应的表名一至,是可以不用标识的。

 

  2、使用 table 特性,定义在system.componentmodel.dataannotations中

[table("products")]

 public sealed class azproducts

    {

    ...

    }

 会返回形如  select ...  from products

 

 3、使用 tablename特性,定义在sqlrepoex.core.customattribute中

[tablename("products")]

 public sealed class azproducts

    {

...

    }

 同样会返回形如  select ...  from products

 当然,使用哪种,按各自的喜好

 

 二、关键字段

 1、如果未使用任何特性,在使用,for() 方法时,不会自动的产生where条件语句。

    [table("products")]

    public sealed class azproducts

    {

public int productid { get; set; }

...

    }

 当使用

 azproducts azproducts = new azproducts { productname2 = "testvalue", productid = 82 };

var resultupdate = repository.delete().for(azproducts);

只会产生

delete [dbo].[products]

当然,这不所期望的

 

  2、使用 key 特性 table 定义在system.componentmodel.dataannotations中

[table("products")]

 public sealed class azproducts

    {

[key]

public int productid { get; set; }

...

    }

 会返回形如 delete [dbo].[products] where  [productid] = 82;

 

 3、使用 keyfield 特性 table定义在sqlrepoex.core.customattribute中

[tablename("products")]

 public sealed class azproducts

    {

 [keyfield]

 public int productid { get; set; }

...

    }

 同样会返回形如 delete [dbo].[products] where  [productid] = 82;

 

三、标识字段(自增字段)

 1、如果未使用任何特性,在使用,for() 方法时,在增加操作时,不会返回自增自段的实际值。

    [table("products")]

    public sealed class azproducts

    {

public int productid { get; set; }

...

    }

 当使用

azproducts azproducts = new azproducts { productname2 = "testvalue" };

            var resultinsert = repository

                                    .insert()

                                    .for(azproducts);

只会产生

insert [dbo].[products]([productname],[supplierid],[categoryid],[quantityperunit],[unitprice],[unitsinstock],[unitsonorder],[reorderlevel],[discontinued])

values('testvalue',null,null,null,null,null,null,null,0);

 

  2、使用 databasegenerated 特性,定义在system.componentmodel.dataannotations中

[table("products")]

 public sealed class azproducts

    {

[key]

[databasegenerated(databasegeneratedoption.identity)]

public int productid { get; set; }

...

    }

 会返回形如

insert [dbo].[products]([productname],[supplierid],[categoryid],[quantityperunit],[unitprice],[unitsinstock],[unitsonorder],[reorderlevel],[discontinued])

values('testvalue',null,null,null,null,null,null,null,0);

select [productid],[productname] as productname2,[supplierid],[categoryid],[quantityperunit],[unitprice],[unitsinstock],[unitsonorder],[reorderlevel],[discontinued]

from [dbo].[products]

where [productid] = scope_identity();

 

 3、使用 identityfield 特性,定义在sqlrepoex.core.customattribute中

[tablename("products")]

 public sealed class azproducts

    {

[keyfield]

[identityfield]

public int productid { get; set; }

 ...

    }

 同样会返回形如

insert [dbo].[products]([productname],[supplierid],[categoryid],[quantityperunit],[unitprice],[unitsinstock],[unitsonorder],[reorderlevel],[discontinued])

values('testvalue',null,null,null,null,null,null,null,0);

select [productid],[productname] as productname2,[supplierid],[categoryid],[quantityperunit],[unitprice],[unitsinstock],[unitsonorder],[reorderlevel],[discontinued]

from [dbo].[products]

where [productid] = scope_identity();

 

四、非字段属性

1、如果未使用任何特性,如下面属性 public string supplier { get; set; }。此属性在数据库中无对应的字段

    [table("products")]

    public sealed class azproducts

    {

[key]

[databasegenerated(databasegeneratedoption.identity)]

public int productid { get; set; }

public string supplier { get; set; }

...

    }

 当使用

var result = repository.query();

会产生形如

select productid,supplier ....

 

  2、使用 notmapped 特性,定义在system.componentmodel.dataannotations中

[table("products")]

 public sealed class azproducts

    {

[key]

[databasegenerated(databasegeneratedoption.identity)]

public int productid { get; set; }

[notmapped]

public string supplier { get; set; }

 ...

    }

 当使用

var result = repository.query();

时,supplier 不会出现在查询语句中,但要注意,当使用选择器来查询时,何然会出现在select语句中;

如 var result = repository.query().select(c=>c.productid,c=>c.supplier);

 

 3、使用 nondatabasefield 特性,定义在sqlrepoex.core.customattribute中

[tablename("products")]

 public sealed class azproducts

    {

[key]

[databasegenerated(databasegeneratedoption.identity)]

public int productid { get; set; }

[nondatabasefield]

public string supplier { get; set; }

 ...

    }

 当使用

var result = repository.query();

时,supplier 不会出现在查询语句中,但要注意,当使用选择器来查询时,何然会出现在select语句中;

如 var result = repository.query().select(c=>c.productid,c=>c.supplier);

 

五、指定属性对应的数据库字段名

有时,类属性名与数据库中的字段名不完全是一一对应的,所以需要指定实际字段名

使用 column 特性,定义在system.componentmodel.dataannotations中,sqlrepoex中没有对应的特性。

如下列类中的  productname2 属性,对应的数据库字段实为 productname

[tablename("products")]

 public sealed class azproducts

    {

[key]

[databasegenerated(databasegeneratedoption.identity)]

public int productid { get; set; }

[nondatabasefield]

public string supplier { get; set; }

[column("productname")]

 public string productname2 { get; set; }

         ...

    }