在使用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. javascript 保护变量不被随意修改------优雅的编程

    /* * 1.如果在renderTitle,renderContent里面,这样总数据谁都能修改,不安全 * 改进 * 1.规定一个专门修改数据的方法,如果想修改数据只能走这个方法 * * actio ...

  2. ST 表学习

    作用:ST算法是用来求解给定区间RMQ的最值,本文以最小值为例 举例: 给出一数组A[0~5] = {5,4,6,10,1,12},则区间[2,5]之间的最值为1. 方法:ST算法分成两部分:离线预处 ...

  3. C++函数的重载,覆盖和隐藏(——高质量编程第14章)

      函数重载概念 只有C++才有重载的概念,C语言没有. 靠行参列表的不同来区别不同的重载函数, 若是全局函数和成员函数同名时,不算重载,因为它们的作用域不同,所以成员函数会将全局函数给隐藏(遮蔽)了 ...

  4. 出现 Assigning the return value of new by reference is deprecated in xxxx &&“Warning: Call-time pass-by-reference has been deprecated”怎么办?

    自从php5.3,越来越多的人会遇到“Assigning the return value of new by reference is deprecated in xxxx”这样的提示,尤其是在国外 ...

  5. loj6173 Samjia和矩阵(后缀数组/后缀自动机)

    题目: https://loj.ac/problem/6173 分析: 考虑枚举宽度w,然后把宽度压位集中,将它们哈希 (这是w=2的时候) 然后可以写一下string=“ac#bc” 然后就是求这个 ...

  6. lombok注解

    官方文档:@EqualsAndHashCode 转:https://blog.csdn.net/zhanlanmg/article/details/50392266 1. 此注解会生成equals(O ...

  7. [转]Wireshark抓包工具--TCP数据包seq ack等解读

    原文: http://blog.csdn.net/wang7dao/article/details/16805337/ ---------------------------------------- ...

  8. 全文检索(二)-基于lucene4.10的增删改查

    今天 用lucene完毕了 一个简单的web应用.提取了早期编写的一个測试类. 首先简单介绍下lucene几个经常使用包; lucene 包的组成结构:对于外部应用来说索引模块(index)和检索模块 ...

  9. 浅谈JavaScript的面向对象程序设计(三)

    前面已经对JavaScript的面向对象程序设计作了简单的介绍,包括了对象的属性.对象的工厂模式.构造函数和原型等.通过介绍,这些创建对象的方法依然有不少优化和改进的地方. 组合使用构造函数模式和原型 ...

  10. 2016/04/29 smarty模板 1, 初步 目标 : 变量 运算符 表达式 流程控制 函数

    ① 从配置文件中读取配置: 1,在模板页面加载配置文件 html页面 不是php页面 <{config_load file='fo.conf'}> 2,在需要用到配置的地方加 <{# ...