讲讲Linq to SQL映射(基础篇)

这篇主要讲Linq to  SQL基于属性的映射。即映射数据库,映射表,映射列,映射关系,映射存储过程,

映射函数。然而创建这种映射有三种方法,他们分别是ORD工具,SQLMetal命令行工具,以及编写手工代码

创建。

咱们首先了解下手工创建属性映射的方法,这样你就能看懂基于工具产生的代码了。他们的区别也就是

使用工具效率会更高些,但前提需要先设计好数据库,这样就可以直接通过数据库的结构输出你的实体类。

1、映射数据库

映射数据库主要通过Database属性来指定,引用命名空间System.Data.Linq.Mapping;

具体看如下代码:

//这里在连接的时候 如果MyDatabase不指定Database属性,生成的数据库名为MyDbContext类名
//如果指定,则为Database属性里的名称,在这里生成的数据库名为IThinks
[Database(Name = "IThinks")]
public class MyDbContext : DataContext
{
//必须构建此表,不然创建数据库时会提示没有表,无法创建。
public Table<LoginUser> LoginUsers;
public Table<UserBaseInfo> UserBaseInfos;
public Table<Aritcal> Articals;
public MyDbContext(string connection) : base(connection)
{
}
}

然后再创建数据库连接的时候,就可以这样写,如果database 不设置的话,默认的数据库名就会为MyDbContext 类名:

MyDbContext db = new MyDbContext("Data Source=localhost;Integrated Security=true;");

这样的话,输出的连接sql语句为:

2、映射表

映射表使用的attribute属性为Table

//Table:映射数据库中对应表或视图名,NAME指定数据库表名,若无此表,创建数据库时,会自动创建
[Table(Name="UserBaseInfo")]
public class UserBaseInfo

3、映射列

映射列使用的attribute属性为Column,参数设置比较多,具体看如下代码:

       //Column:映射数据库表中字段 其特性为:
//Name:数据库中列的名称
//DbType:数据库列的数据库类型
//Storage:获取或设置私有存储字段以保存列值
//IsPrimaryKey:指示所关联的列是否是相应表的主键 默认false
//CanBeNull:指示所关联的列能否包含空值
//CanBeNull不能乱用,如果某列CanBeNull设置为true,但从数据库中查出来的值为null的话,
//这一列在update的时候会提示找不到此行或行已更改,因为其查询的语句为where 0 = 1 所以找不到
//可以查看:http://stackoverflow.com/questions/2275442/linq-update-query-generates-where-0-1
//
如果你非要设置canbenull=true,可以通过继续设置其updatecheck为never或whenchanged来规避where 0=1这个问题。
//
AutoSync:在执行insert或者update操作之后获取列值,默认为never;
//UpdateCheck:即设置是否检查冲突,默认是Always
//IsDbGenerated=true 是否数据库自动生成值,如果设置为true的话,那么在实例化实体给此列赋值将会无效,在执行插入时,会传值为null进入
//如果这时候数据库未给予默认值或值自增设置,则会报此字段为空的错误,虽然你在实例化时已经赋值。 

        [Column(DbType = "int", IsPrimaryKey = true, IsDbGenerated = true)]
public int UserID { get; set; }
[Column(DbType = "nvarchar(50) not null", CanBeNull = false, UpdateCheck = UpdateCheck.WhenChanged)]
public string UserName { get; set; }
[Column(DbType = "nvarchar(50)", CanBeNull = false, UpdateCheck = UpdateCheck.Never)]
public string UserNickName { get; set; }

4、映射关系

这里的关系是指的数据库中一对多和一对一。主键基表和外键基表的设置也能通过实体字段的Association属性(IsForeignKey=true)来进行关联,从而在创建数据库时,自动创建表之间的关系。

但要结合EntityRef<T>或 EntitySet<T> 来定义并表示一个关系

EntityRef代表一对多关系中的单一实例方,EntitySet主要代表一对多和一对一关系中的集合方,下面分别用代码介绍

以用户基本信息表 UserBaseInfo和用户文章表Aritcal来作为介绍,他们是一对多的关系

1)EntityRef+Association的使用

因为EntityRef代表的是1:M关系中的1,所以它应该为Aritcal实体的成员,泛型对象为UserBaseInfo

这里UserBaseInfo的实体和Artical实体分别为:

  //Table:映射数据库中对应表或视图名,若无此表,会自动创建
[Table(Name = "UserBaseInfo")]
public class UserBaseInfo
{ [Column(DbType = "int", IsPrimaryKey = true, IsDbGenerated = true)]
public int UserID { get; set; }
[Column(DbType = "nvarchar(50) not null", CanBeNull = false, UpdateCheck = UpdateCheck.WhenChanged)]
public string UserName { get; set; }
private EntitySet<Aritcal> _Artiacle;
[Association(ThisKey = "UserID", OtherKey = "UserID")]
public EntitySet<Aritcal> Articals
{
get { return _Artiacle; }
set { _Artiacle.Assign(value); }
}
}
[Table(Name = "Artical")]
public class Aritcal
{
[Description("文章ID"), Column(IsPrimaryKey = true, CanBeNull = false, DbType = "int not null")]
public int ArticalID { get; set; }
[Description("用户ID"), Column(CanBeNull = false, DbType = "int not null")]
public int UserID { get; set; }
[Description("文章标题"), Column(DbType = "nvarchar(100) not null", UpdateCheck = UpdateCheck.Never)]
public string ArticalTitle { get; set; }
[Description("文章分类"), Column(DbType = "int not null", UpdateCheck = UpdateCheck.Never)]
public int CategoryID { get; set; }
[Description("模块分类"), Column(DbType = "int", UpdateCheck = UpdateCheck.Never)]
public int ModuleID { get; set; }
[Description("文章内容"), Column(DbType = "ntext not null", UpdateCheck = UpdateCheck.Never)]
public string Content { get; set; }
private EntityRef<UserBaseInfo> _UserBaseInfo;
//Name:外键名
//ThisKey:外键表的外键列 可以不为主键 除非1:1关系中
//OtherKey:主键表的主键列 必须是主键
//IsForeignKey:是否外键
//Storage:用来存储的变量
[Association(Name = "FK_Aritcal_UserBaseInfo_UserID", ThisKey = "UserID", OtherKey = "UserID", IsForeignKey = true,
        Storage = "_UserBaseInfo")]
public UserBaseInfo UserBaseInfo
{
get { return _UserBaseInfo.Entity; }
set { _UserBaseInfo.Entity = value; }
}
}

这样Artical自动创建外键,生成的表结构关系为

2)下面在讲下EntitySet<T> 和Association

在UserBaseInfo表中创建下面成员,这样做的好处是,进行数据库关联查询时便能查询出数据

        private EntitySet<Aritcal> _Artiacle;
[Association(ThisKey = "UserID", OtherKey = "UserID")]
public EntitySet<Aritcal> Articals
{
get { return _Artiacle; }
set { _Artiacle.Assign(value); }
}
见查询代码:  查询用户信息表中用户ID为1的用户信息,通过调用Articals成员,自动关联查询出用户id为1的文章列表
            UserBaseInfo userbase = db.GetTable<UserBaseInfo>().Where(a => a.UserID == 1).FirstOrDefault();
foreach (Aritcal artical in userbase.Articals.ToList())
{
Console.WriteLine(string.Format("userid:{0} aritical userid:{1} articalid:{2} ispublist{3}",
userbase.UserID, artical.UserID, artical.ArticalID, artical.IsPublish));
}

查询结果如下:

5、映射存储过程

通过调用Function属性实现调用存储过程,只有一个Name特性,来指定存储过程的名称

如下面的实例通过用户名ID,获取用户的密码:

首先创建存储过程

create  procedure [dbo].[GetPassword]
(@userid int ,
@password nvarchar(30) output
)
as
begin
select @password = c.Password from LoginUser c where c.UserID=@userid
end
然后在MyDbContext类中添加如下方法
        /// <summary>
/// 获取用户密码
/// </summary>
/// <param name="userid">用户名ID</param>
/// <param name="password">用来返回获取到的密码</param>
/// <returns></returns>
[Function(Name = "GetPassword")]
public int GetPassword([Parameter(DbType = "int")] int userid, [Parameter(DbType = "nvarchar(30)")] out string password)
{
password = "";
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()), userid, password);
password = (string)result.GetParameterValue(1); //返回需要的密码数据 必须用out 或者ref引用,不然得到空值
return (int)result.ReturnValue; //这里返回0 表示执行成功
}

调用代码如下:

           string  str;
db.GetPassword(userbase.UserID, out str);
Console.WriteLine("pwd:"+str);

调用结果如下:

6、映射函数

用户自定义函数(UDF)在linq to sql中用到的属性是一样的,不过函数和存储过程的区别导致了函数只能返回单个值,而不能像存储过程那样返回多个参数

具体实现看如下代码

首先在数据库中定义函数

--创建通过用户ID获取密码的函数
create function Fun_GetPassword
(@userid int )
returns nvarchar(30)
as
begin
declare @password nvarchar(30)
select @password = c.Password from LoginUser c where c.UserID=@userid
return @password
end

然后在vs中编写代码调用

       //调用函数 这里要加dbo.,不然你若返回的不是表,则会提示Fun_GetPassword不是可以识别的 内置函数名称。
//另外调用函数,要定义IsComposable特性为true,这样他才知道是调用的存储过程
[Function(Name = "dbo.Fun_GetPassword", IsComposable = true)]
public string Fun_GetPassword([Parameter(DbType = "int")] int userid)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()), userid);
return (string)result.ReturnValue;
} //调用自定义函数 获取密码
string mypwd= db.Fun_GetPassword(userbase.UserID);
Console.WriteLine("pwd:"+mypwd);

调用结果如下:

下载源码

讲讲Linq to SQL映射(基础篇)的更多相关文章

  1. oracle(sql)基础篇系列(五)——PLSQL、游标、存储过程、触发器

      PL/SQL PL/SQL 简介 每一种数据库都有这样的一种语言,PL/SQL 是在Oracle里面的一种编程语言,在Oracle内部使用的编程语言.我们知道SQL语言是没有分支和循环的,而PL语 ...

  2. oracle(sql)基础篇系列(五)——PLSQL、游标、存储过程、触发器

    PL/SQL PL/SQL 简介 每一种数据库都有这样的一种语言,PL/SQL 是在Oracle里面的一种编程语言,在Oracle内部使用的编程语言.我们知道SQL语言是没有分支和循环的,而PL语言是 ...

  3. SQL——语法基础篇(上)

    用数据库的方式思考SQL是如何执行的 虽然 SQL 是声明式语言,我们可以像使用英语一样使用它,不过在 RDBMS(关系型数据库管理系统)中,SQL 的实现方式还是有差别的.今天我们就从数据库的角度来 ...

  4. oracle(sql)基础篇系列(一)——基础select语句、常用sql函数、组函数、分组函数

        花点时间整理下sql基础,温故而知新.文章的demo来自oracle自带的dept,emp,salgrade三张表.解锁scott用户,使用scott用户登录就可以看到自带的表. #使用ora ...

  5. oracle(sql)基础篇系列(一)——基础select语句、常用sql函数、组函数、分组函数

    花点时间整理下sql基础,温故而知新.文章的demo来自oracle自带的dept,emp,salgrade三张表.解锁scott用户,使用scott用户登录就可以看到自带的表. #使用oracle用 ...

  6. sql优化基础篇

    优化的步骤: 0.先sql运行看看是否真的很慢,注意设置SQL_NO_CACHE 1.where条件单表查,锁定最小返回记录表.这句话的意思是把查询语句的where都应用到表中返回的记录数最小的表开始 ...

  7. oracle(sql)基础篇系列(三)——数据维护语句、数据定义语句、伪列

      DML语句 insert 向表中插入新的记录   --三种插入方式 --(1)不写字段的名字,直接按照字段的顺序把值逐个往里插 insert into dept2 values(50,'DANAM ...

  8. oracle(sql)基础篇系列(二)——多表连接查询、子查询、视图

        多表连接查询 内连接(inner join) 目的:将多张表中能通过链接谓词或者链接运算符连接起来的数据查询出来. 等值连接(join...on(...=...)) --选出雇员的名字和雇员所 ...

  9. 2019.3.22 SQL语句(基础篇)

    SQL语句 创建一个数据库: create database+数据库名; 使用数据库: use+数据库名; 查看mySQL中有哪些数据库: show databases; 删除数据库 drop dat ...

随机推荐

  1. Linux C/C++计划Shell命令大杂烩(1)

    1, 请参见发行信息 cat /etc/issue 2, 查看内核版本号 uname -r 查看内核版本号 uname -p 查看处理器类型32bit/64bit uname -n 查看网络主机名(o ...

  2. passenger安装nginx

    1.更换淘宝gem gem sources --remove https://rubygems.org/ gem sources -a https://ruby.taobao.org/ 2.gem安装 ...

  3. DBUtils的使用

    DButils是apache旗下Commons项目中的一个JDBC工具包,它可以为帮助我们简化对JDBC的操作,但它并不是一个ORM框架,只是可以为我们执行sql,并将返回的ResultSet转化成我 ...

  4. [CLR via C#]1.2 将托管模块合并成程序集

    原文:[CLR via C#]1.2 将托管模块合并成程序集 1.CLR是不和托管模块一起工作的,CLR是和程序集一起工作的. 2. 程序集是一个或多个托管模块/资源文件的逻辑性分组.   3. 程序 ...

  5. 自由软件之父、Google+设计者、Java之父、Linux之父、万维网之父、Vi编辑器之父、苹果Lisa电脑界面设计、微软首席软件架构师

    自由软件之父.Google+设计者.Java之父.Linux之父.万维网之父.Vi编辑器之父.苹果Lisa电脑界面设计.微软首席软件架构师 理查德·斯托曼(Richard Stallman) 理查德· ...

  6. ASP.NET MVC性能优化工具 MiniProfiler

    ASP.NET MVC性能优化工具 MiniProfiler 2014年04月19日 ⁄ ASP.NET ⁄ 共 1159字 ⁄ 字号 小 中 大 ⁄ 暂无评论 ⁄ 阅读 325 views 次 MV ...

  7. SEO 优化,网站推广优化教程100条(SEO,网站关键字优化,怎么优化网站,如何优化网站关键字)

    这篇文章不错.  http://www.cnblogs.com/zangdalei/archive/2010/08/31/1814047.html 看了一半之后的,觉得不太靠谱,很多都不懂. 于是 找 ...

  8. [Unity3D]Unity3D游戏开发Android内嵌视图Unity查看

    ---------------------------------------------------------------------------------------------------- ...

  9. poj 2513 Colored Sticks(欧拉路径+并检查集合+特里)

    题目链接:poj 2513 Colored Sticks 题目大意:有N个木棍,每根木棍两端被涂上颜色.如今给定每一个木棍两端的颜色.不同木棍之间拼接须要颜色同样的 端才干够.问最后是否能将N个木棍拼 ...

  10. OpenStreetMap架构

    OpenStreetMap框架简介 1.OSM平台开发 OpenStreetMap(缩写OSM)地图是一个合作项目,我们的目标是创建一个免费的内容,让所有的人都可以编辑的世界地图. OSM在地图上由一 ...