asp.net MVC Model 类的主键 int类型、string类型、GUID类型。
在使用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类型。的更多相关文章
- ASP.NET MVC Model验证(三)
ASP.NET MVC Model验证(三) 前言 上篇中说到在MVC框架中默认的Model验证是在哪里验证的,还讲到DefaultModelBinder类型的内部执行的示意图,让大家可以看到默认的M ...
- ASP.NET MVC Model绑定(二)
ASP.NET MVC Model绑定(二) 前言 上篇对于Model绑定的简单演示想必大家对Model绑定的使用方式有一点的了解,那大家有没有想过Model绑定器是在什么时候执行的?又或是执行的过程 ...
- ASP.NET MVC Model元数据(五)
ASP.NET MVC Model元数据(五) 前言 在上一篇中我们描述了应用于Model上面的各种用于显示控制的特性类,在本篇中将详细的介绍这些特性类的应用,虽然它们跟Model元数据的直接关系并不 ...
- ASP.NET MVC Model验证(五)
ASP.NET MVC Model验证(五) 前言 上篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现, 然而在MVC框架中还给我们提供了其它 ...
- ASP.NET MVC Model验证(四)
ASP.NET MVC Model验证(四) 前言 本篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现,前者是Model验证提供程序,而Mod ...
- ASP.NET MVC Model验证(二)
ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...
- ASP.NET MVC Model验证(一)
ASP.NET MVC Model验证(一) 前言 前面对于Model绑定部分作了大概的介绍,从这章开始就进入Model验证部分了,这个实际上是一个系列的Model的绑定往往都是伴随着验证的.也会在后 ...
- ASP.NET MVC Model绑定(六)
ASP.NET MVC Model绑定(六) 前言 前面的篇幅对于IValueProvider的使用做个基础的示例讲解,但是没并没有对 IValueProvider类型的实现做详细的介绍,然而MVC框 ...
- ASP.NET MVC Model绑定(五)
ASP.NET MVC Model绑定(五) 前言 前面的篇幅对于IValueProvider的获取位置和所处的生成过程做了讲解,本篇将会对IValueProvider的使用做个基础的示例讲解,读完本 ...
随机推荐
- asp.net 引发类型为“System.OutOfMemoryException”的异常
asp.net 引发类型为“System.OutOfMemoryException”的异常通常发生在IIS进程获取不到内存时. 临时解决方法是: 回收IIS的应用程序池. 如果要比较好的解决办法是: ...
- COdevs 1251 括号
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 计算乘法时,我们可以添加括号,来改变相乘的顺序,比如计算X1, X2, X3, X4 ...
- BZOJ1777: [Usaco2010 Hol]rocks 石头木头
n<=10000的树,节点有初始石头数<=1000,进行这样的游戏:两人轮流行动,我先手,每次可以选一个节点(≠1)把不超过m<=1000个石头移到父亲,最后所有石头都在节点1,没法 ...
- php 之mysql安全
php 之mysql安全 原文:https://www.cnblogs.com/mafeng/p/5939329.html. 请浏览原文. 一.服务器配置方面. (1) 打开php的安全模式 php的 ...
- 123. Best Time to Buy and Sell Stock III ~~
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- Spring实战Day2
创建对象之后如何体现对象之间的依赖? Spring容器负责创建Bean和依赖注入,那么Spring是怎么将Bean装配在一起的呢? Spring提供了三种方式装配机制 1.隐式的bean发现机制和自动 ...
- httpclient失败重连机制
HttpClient 底层会默认超时自动重发3次,DefaultHttpRequestRetryHandler源码 /** * Create the request retry handler ...
- 使用Guava适配不同的callback
Cache<Key,Value> cache =CacheBuilder.newBuilder() .maximumSize(1000) .build();// look Ma, no C ...
- hdu1181 dfs搜索之变形课
原题地址 这道题数据据说比較水,除了第一组数据是Yes以外.其余都是No.非常多人抓住这点就水过了.当然了,我认为那样过了也没什么意思.刷oj刷的是质量不是数量. 这道题从题目上来看是个不错的 搜索题 ...
- LeetCode 283 Move Zeroes(移动全部的零元素)
翻译 给定一个数字数组.写一个方法将全部的"0"移动到数组尾部.同一时候保持其余非零元素的相对位置不变. 比如,给定nums = [0, 1, 0, 3, 12],在调用你的函数之 ...