在使用asp.net mvc进行定义 模型类的时候,一般情况下,我们都会定义一个属性为 int iD{get;set;} 或为int ClassNameID {get;set;},在这种情况下

1、Int类型主键

EF的默认约定就是第一个属性如果是类名+id或是id(这两情况下id字母大小写没有关系),并且是int类型的,那么直接设置第一个属性为主键,同时设置自增长。不需要指定[Key]关键字(在 System.ComponentModel.DataAnnotations.Schema命名空间下面)

比如:

public class Person
{
public int ID { get; set; }

public string Name { get; set; }

public int Price { get; set; }

public DateTime Birthday { get; set; }
}

或为

public class Person
{
public int PersonId { get; set; }

public string Name { get; set; }

public decimal Price { get; set; }

public DateTime Birthday { get; set; }
}

此时,如果用脚手架自动创建控制器和视图中,因id或classid已经被认为是主键了,属性在create,index视图中不会显示。

如果在字段加入了[DatabaseGenerated(DatabaseGeneratedOption.None)] 的数据注解,让你自己输入主键值而不是数据库自动创建它。

在新建和编辑视图中自动会将id字段显示出来,供用户输入 。

2、GUiD主键

模型:

public class Person
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]   //此数据注解并可表示可以在数据库中自动生成 GUID值,只是告诉基架 在操作方法中生成创建GUID值的代码。如person.PersonID = Guid.NewGuid();   
public Guid PersonID { get; set; }

public string Name { get; set; }

public int Price { get; set; }

public DateTime Birthdaey { get; set; }

}

利用基架自动创建控制器和视图:

public ActionResult Create()
{
return View();
}

// POST: People/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "PersonID,Name,Price,Birthdaey")] Person person)
{
if (ModelState.IsValid)
{
person.PersonID = Guid.NewGuid();        //基架增加自动创建的代码,指定PersonID GUID属性值。
db.People.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(person);
}

视图:基架生成的视图中已经没有了PersonID 的表单值,因为模型中已经注明 了有数据库自动创建。

using (Html.BeginForm())
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
<h4>Person</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })

<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>

<div class="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div>

3、string类型主键,如果一个模型的属性名为ID或classNameID 它总被认为主键,在映射到数据库总是为主键值,也不需要Key数据注解。不管它的类型是int 还是string,还是GUID。如果是int型,被认为是自增长,自动生成的创建编辑视图不会显示此字段。如果是string类型,不会自增长,需要用户输入或指定,自动生成的创建编辑视图会显示此字段,提示用户输入。

第一种方式:给模型创建一个构造函数指定PersonID为GUID字符串,在Create 视图中,删除脚手架自动生成的PerosnID 表单字段值。在Creater的POST方法中模型绑定自动生成一个Person对象,它的PersonID=GUID的值。这是使用主键类型为string的最佳实践。

模型:

public class Person
{
public string PersonID { get; set; } //由于属性名 为classNameID ,因此被认为主键。但是它不会自增长。需要用户自行生成。

public string Name { get; set; }

public decimal Price { get; set; }

public DateTime Birthday { get; set; }

public Person()
{
PersonID = Guid.NewGuid().ToString();
}

控制器:

// GET: People/Create
public ActionResult Create()
{
return View();
}

// POST: People/Create
// 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
// 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "PersonID,Name,Price,Birthday")] Person person)//是否绑定PersonID都不影响。
{
if (ModelState.IsValid)  //模型绑定将自动创建一个Person对象,调用Person的构造函数生成GuiD 主键值。
{
db.People.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(person);
}

视图:删除自动生成的PerserID表单字段。

@using (Html.BeginForm()) 
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
<h4>Person</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })   //删除PersonID的表单字段,如果不删除,那么PersonID的值就会要求手动输入,不输入就会绑定到POST方法中的PersonID为空值,保存的数据库就会出错。

<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>

<div class="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div>

在Asp.net Identity 中默认使用的String 类型的主键值,也是相同的实现方法。只不过,我们在访问Applicationuser 的时候绑定用的大多数是ViewModel,而不是直接的ApplicationUser或基类IdentityUser 类。

查看到ApplicationUser class(和用户相关的类)继承了IdentityUser.cs (位于Microsoft.Asp.Net.Identity.EntityFramework.dll) 反编译后源码如下:

 1 namespace Microsoft.AspNet.Identity.EntityFramework
2 {
3 using Microsoft.AspNet.Identity;
4 using System;
5
6 public class IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>
7 {
8 public IdentityUser()
9 {
10 this.Id = Guid.NewGuid().ToString();
11 }
12
13 public IdentityUser(string userName) : this()
14 {
15 this.UserName = userName;
16 }
17 }
18 }

观察 IdentityUser.cs 它有继承了IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>这个泛型,所以我们也需要有对应的Int类型的 IdentityUserLogin, IdentityUserRole, IdentityUserClaim泛型类。

第二种方式:直接在控制器Crate POST方法中指定一个PersonID 值。

模型类保持不变,不使用构造函数

public class Person
{
public string PersonID { get; set; }

public string Name { get; set; }

public decimal Price { get; set; }

public DateTime Birthday { get; set; }

}

控制器:

Create 的Get方法保持与脚手架一致,不作改动。

POst方法去除对PersonID的绑定,(不去也无所谓。)

public ActionResult Create()
{
return View();
}

// POST: People/Create
// 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关
// 详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=317598。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Name,Price,Birthday")] Person person)  
{
if (ModelState.IsValid)
{
person.PersonID = Guid.NewGuid().ToString();     //在POST方法中创建一个GUID值,转换成字符串,并赋值给PersonID属性。
db.People.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(person);
}

视图中删去显示输入PersornID的表单字段。

第三种方式:在Create Get方法中创建一个空的对象,自动调用构造函数生成主键值,返给视图,然后提交表单,将ID值通过模型绑定再传给Create Post方法。这种方式相对于前两种方式暴露给了用户GUID的值了。

控制器:

模型

public class Person
{
public string PersonID { get; set; }  //由于属性名  为classNameID ,因此被认为主键。但是它不会自增长。需要用户自行生成。

public string Name { get; set; }

public decimal Price { get; set; }

public DateTime Birthday { get; set; }

public Person()
{
PersonID = Guid.NewGuid().ToString();

}

public ActionResult Create()
{
Person person = new Person();  //可以在脚手架代码加入此项,调用 自定义的构造函数给 Create视图中的对象返回一个GUID值。
return View(person);
}

// POST: Desks/Create

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = PersonID,Name,Price,Birthday")] Person person) //绑定表单传过来的personID值。
{
if (ModelState.IsValid)
{
db.People.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}

return View(person);
}

}

Create视图代码:

@Html.ValidationSummary(true, "", new { @class = "text-danger" })

<div class="form-group">
@Html.LabelFor(model => model.PersonID, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.PersonID, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.PersonID, "", new { @class = "text-danger" })
</div>
</div>

为了不让主键字段在Create 视图中显示,可以使用@html.HiddenFor(model =>model.personID) 辅助方法代替上面的视图代码。

总结:在使用asp.net MVC codefirst进行开的时候,模型POCO类的主键可定义为int类型,GUID类型(避免主键值在各表中重复,String类型(由GUID值转换)。可以方便的利用基架自动生成 控制器的CRUD操作方法和相应的视图。

如果一个模型的属性名为ID或classNameID 它总被认为主键,在映射到数据库总是为主键值,也不需要Key数据注解。

asp.net MVC Model 类的主键 int类型、string类型、GUID类型。的更多相关文章

  1. ASP.NET MVC Model验证(三)

    ASP.NET MVC Model验证(三) 前言 上篇中说到在MVC框架中默认的Model验证是在哪里验证的,还讲到DefaultModelBinder类型的内部执行的示意图,让大家可以看到默认的M ...

  2. ASP.NET MVC Model绑定(二)

    ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...

  3. ASP.NET MVC Model元数据(五)

    ASP.NET MVC Model元数据(五) 前言 在上一篇中我们描述了应用于Model上面的各种用于显示控制的特性类,在本篇中将详细的介绍这些特性类的应用,虽然它们跟Model元数据的直接关系并不 ...

  4. ASP.NET MVC Model验证(五)

    ASP.NET MVC Model验证(五) 前言 上篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现, 然而在MVC框架中还给我们提供了其它 ...

  5. ASP.NET MVC Model验证(四)

    ASP.NET MVC Model验证(四) 前言 本篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现,前者是Model验证提供程序,而Mod ...

  6. ASP.NET MVC Model验证(二)

    ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...

  7. ASP.NET MVC Model验证(一)

    ASP.NET MVC Model验证(一) 前言 前面对于Model绑定部分作了大概的介绍,从这章开始就进入Model验证部分了,这个实际上是一个系列的Model的绑定往往都是伴随着验证的.也会在后 ...

  8. ASP.NET MVC Model绑定(六)

    ASP.NET MVC Model绑定(六) 前言 前面的篇幅对于IValueProvider的使用做个基础的示例讲解,但是没并没有对 IValueProvider类型的实现做详细的介绍,然而MVC框 ...

  9. ASP.NET MVC Model绑定(五)

    ASP.NET MVC Model绑定(五) 前言 前面的篇幅对于IValueProvider的获取位置和所处的生成过程做了讲解,本篇将会对IValueProvider的使用做个基础的示例讲解,读完本 ...

随机推荐

  1. 虫食算(codevs 1064)

    题目描述 Description 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045    +    8468#6 ...

  2. 通过分析system_call中断处理过程来深入理解系统调用

    通过分析system_call中断处理过程来深入理解系统调用 前言说明 本篇为网易云课堂Linux内核分析课程的第五周作业,上一次作业中我以2个系统调用(getpid, open)作为分析实例来分析系 ...

  3. 移动web页面字体大小二

    按设计稿中的字体大小设置页面字体大小(px),在手机端,因为不同设备会有不同,换算成rem单位.rem是“font size of the root element”,可以通过这篇文章了解http:/ ...

  4. poj2767,单向连通图判定,缩点+重新建图+新图DFS

    /*该题被博客里标记为中等题,30分钟内1A,掌握了算法就简单了,单向连通图判定,单向连通图缩点 后必然唯一存在出度为0的点和入度为0的点,并且从入度为0的点出发,可以遍历所有点后到达出度为0点 (一 ...

  5. ubuntu 14.04 安装docker,docker-compose

    通过阿里的镜像安装 curl -sSL http://acs-public-mirror.oss-cn-hangzhou.aliyuncs.com/docker-engine/internet | s ...

  6. 牛客网暑期ACM多校训练营(第九场) A题 FWT

    链接:https://www.nowcoder.com/acm/contest/147/A来源:牛客网 Niuniu has recently learned how to use Gaussian ...

  7. React学习及实例开发(二)——用Ant Design写一个简单页面

    本文基于React v16.4.1 初学react,有理解不对的地方,欢迎批评指正^_^ 一.引入Ant Design 1.安装antd yarn add antd 2.引入 react-app-re ...

  8. Topcoder SRM 657DIV2

    前言: 像我这样一直在DIV2的弱菜..不知道说什么了. A:一定判断有8个‘R’,每行 每列只有一个 B题:大概是  int E,int EM,int M,int MH,int H 然后EM可以给值 ...

  9. C++开发人脸性别识别教程(8)——搭建MFC框架之读取目录信息

    在上一篇博客中我们已经绘制了MFC界面,在这篇博客中我们将加入响应代码,为MFC框架加入一个最主要的功能:打开一个目录. 一.加入相关头文件 这里头文件主要包括三类:opencv头文件.批量读取文件相 ...

  10. Linux学习笔记总结

    零.求人不如求已:        1. 在Linux中,文件,目录,驱动,命令,脚本都视为文件,也即一切皆file. 2.记住使用Linux 的关键就是六个字: 命令.选项.參数. 3.学会看帮助,不 ...