EF6学习笔记(六) 创建复杂的数据模型
EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)
本篇原文地址:Creating a More Complex Data Model
本篇讲的比较碎,很多内容本人认为并不是EF的内容,既然原文讲了,那就按照原文来学习吧。。。
第1步:通过属性来定制化数据模型
通过 DataType Attribute来定义数据模型字段属性:
先加申明 using System.ComponentModel.DataAnnotations;
然后为需要定义属性的字段加上属性:(例如EnrollmentDate 加上日期DataType,以及显示格式的属性)
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; namespace EFTest.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
DataType 枚举可以通过 DataType Enumeration链接来查看;主要有用的是:Date,Time,EmailAddress,Password等;
通过DataType定义的数据属性,在应用中得到特殊的数据处理功能,比如Email的话,就在显示的时候自动变为点击发Email的Link;如果Date的话,会在前端自动显示为一个日期输入选择框(在HTML5的情况下);
但是DataType不提供验证功能,并且也不特别指定显示格式,默认的显示格式基于服务器的CultureInfo
DispalyFormat属性定义就是用来明确定义显示格式;
DisplayFormat可以单独使用,但建议是配合DataType一起使用,配合使用会有以下优点:
1、HTML5支持的浏览器可以根据DataType做出一些特定的调整及显示(比如会显示计算器、日期输入框、Email地址链接等等)
2、默认情况下,浏览器会根据客户端计算机的本地化显示设置来进行渲染(比如本地化的日期时间格式)
3、DataType属性可以让MVC选择正确的字段类型去渲染数据,DisplayFormat使用字符串类型模板;
更多的信息可以参考:MVC 5 Introduction: Examining the Edit Methods and Edit View
通过StringLength 属性定义长度
可以通过StringLength这个属性来定义一个字段的最长长度,并且可以设置出现错误后应该提供的错误信息;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; namespace EFTest.Models
{
public class Student
{
public int ID { get; set; }
[StringLength()]
public string LastName { get; set; }
[StringLength(, ErrorMessage = "First name 不可以超过50个字符.")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
比如设定LastName、FirstMidName最长只能50个字符,并且在FirstMidName输入超过50个字符的时候提示相应错误;
另外,StringLength属性定义不能防止用户输入空格,所以可以通过RegularExpression来进行限制:
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]
以上这个属性定义,限制首字母为大写,后面也必须为字母;
PS: MaxLength属性定义也能定义字段最大长度,但是并不提供客户端验证。
这个时候如果直接运行应用,并点击Students页面,就会有以下错误:
说明数据模型变了,数据库也需要先升级才可以;
先在PM控制台执行 add-migration MaxLengthOnNames
会自动创建一个带时间戳的数据升级文件;然后在PM控制台继续输入:update-database
完成后,就可以再次尝试进入应用的Student页面,并点击Create进入新建页面:
Column 属性定义:当一些特定情况下,希望数据库里的字段名采用一个约定格式名,而模型中是另一个名称,则需要通过Column来强制换个名字:
首先,添加申明:using System.ComponentModel.DataAnnotations.Schema;
然后用[Column("NewColumnName")] 定义数据库中的列名:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public class Student
{
public int ID { get; set; }
[StringLength()]
public string LastName { get; set; }
[StringLength(, ErrorMessage = "First name 不可以超过50个字符.")]
[Column("FirstName")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime EnrollmentDate { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
当然,在做了这个改动后,需要今天数据库升级操作:
在PM控制台输入以下命令:
add-migration ColumnFirstName
update-database
更新后,列名变了,并且DataType从nvarchar(MAX) 变为 nvarchar(50):
PS: 这个操作可以通过 Fluent API 来完成,后面也会提及到。
将Student模型变更为以下完整版本:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public class Student
{
public int ID { get; set; }
[Required]
[StringLength()]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[StringLength(, ErrorMessage = "First name 不可超过50个字符.")]
[Column("FirstName")]
[Display(Name = "First Name")]
public string FirstMidName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Enrollment Date")]
public DateTime EnrollmentDate { get; set; } [Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
} public virtual ICollection<Enrollment> Enrollments { get; set; }
} }
[Required]对于值类型的是不需要的,例如int , DateTime, double, float ,因为这些值本身是不可以为空NULL的;
对于字符串类型的属性(property),可以通过设置最小长度来代替[Required]:
[Display(Name = "Last Name")]
[StringLength(, MinimumLength=)]
public string LastName { get; set; }
Display定义在显示View的时候,对应该属性(property)的输入框标题内容;
另外,FullName是一个计算出来的属性(property),所以只有get ,没有set ,这样在数据库里是不会增加 FullName这个列的;
新建Instructor模型:(和Student 模型差不多)
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public class Instructor
{
public int ID { get; set; } [Required]
[Display(Name = "Last Name")]
[StringLength()]
public string LastName { get; set; } [Required]
[Column("FirstName")]
[Display(Name = "First Name")]
[StringLength()]
public string FirstMidName { get; set; } [DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Hire Date")]
public DateTime HireDate { get; set; } [Display(Name = "Full Name")]
public string FullName
{
get { return LastName + ", " + FirstMidName; }
} public virtual ICollection<Course> Courses { get; set; }
public virtual OfficeAssignment OfficeAssignment { get; set; }
} }
当然也可以简化属性定义为一行:(通过逗号来分割)
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public class Instructor
{
public int ID { get; set; } [Display(Name = "Last Name"), StringLength(, MinimumLength = )]
public string LastName { get; set; } [Column("FirstName"), Display(Name = "First Name"), StringLength(, MinimumLength = )]
public string FirstMidName { get; set; } [DataType(DataType.Date), Display(Name = "Hire Date"), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime HireDate { get; set; } [Display(Name = "Full Name")]
public string FullName
{
get { return LastName + ", " + FirstMidName; }
} public virtual ICollection<Course> Courses { get; set; }
public virtual OfficeAssignment OfficeAssignment { get; set; } } }
在Instructor模型中 Courses 和 OfficeAssignment为导航属性,采用virtual来定义为延迟加载;
Instructor对应Courses 是1对n ,所以采用ICollection<T>来表示;
Instructor对应OfficeAssignment是1对1,所以直接采用OfficeAssignment来定义;
新建OfficeAssignment模型:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public class OfficeAssignment
{
[Key]
[ForeignKey("Instructor")]
public int InstructorID { get; set; }
[StringLength()]
[Display(Name = "Office Location")]
public string Location { get; set; } public virtual Instructor Instructor { get; set; }
} }
Instructor对应OfficeAssignment是1对1或者 1对0,即OfficeAssignment表中的InstructorID一定是在Instructor存在这个ID的;
所以对于OfficeAssignment InstructorID
需要设置为主键,并且要定义为从Instructor ID来的外键;
修改Course模型
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Name = "Number")]
public int CourseID { get; set; } [StringLength(, MinimumLength = )]
public string Title { get; set; } [Range(, )]
public int Credits { get; set; } public int DepartmentID { get; set; } public virtual Department Department { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
public virtual ICollection<Instructor> Instructors { get; set; }
} }
新建Department模型
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace EFTest.Models
{
public class Department
{
public int DepartmentID { get; set; } [StringLength(, MinimumLength = )]
public string Name { get; set; } [DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Budget { get; set; } [DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; } public int? InstructorID { get; set; } public virtual Instructor Administrator { get; set; }
public virtual ICollection<Course> Courses { get; set; }
} }
最后希望的模型定义图:
做些总结汇总:
1、模型中Properties如果名称为ID或者是类名+ID,则EF会自动将其变为主键;
2、如果主键为int型,默认会定义为数据库自增长的类型,除非用 [DatabaseGenerated(DatabaseGeneratedOption.None)] 来明确告知不要;
3、如果是1对1或0的对应关系,需要明确用[ForeignKey("XXXX")]来告知EF哪个是主表哪个是子表,不然会报异常;
4、如果是多对1或0的对应关系,如果Properties是值类型,则需要用 问号 来定义可以为空;
5、默认情况下,EF是开启联级删除(cascade delete),那么如果外键导致的联级删除出现多个
例如: A -> B 是 1对多, A -> C 也是 1对多, B 和 C 是多对多, 那么要删除 一个A,就需要联级删除先删除 B 和 C ,而要删除B 和 C 就要先删除 B 和 C 连接对应;
这样就有两条路都到删除 B 和 C 的连接关系,这个是数据库所不允许的;
那么只有两种方式:
a) fluent API来申明关闭这个A的cascade delete;
b) 把A -> B设置为 0,1对多,或者 A -> C 设置为 0,1对多, 即删除A时,不是删除B,而是把B里涉及到A的外键列值设置为NULL。
6、如果是多对多的关系,则EF会自动新建一个表来存储多对多的关系;
在上下文类中通过Fluent API来定义复杂模型关系及一些设定
在上下文类中增加定义所有的实体,并通过Fluent API来定义一些设定;
Fluent API可以用来设定绝大部分的模型关系及定义,但是也有一些不可以用Fluent API来设定,比如 MinimumLength
因为MinimumLength
不会对数据库结构产生影响,而只是对客户端验证起作用;
有点程序员比较喜欢用Fluent API,这样模型定义看起来“干净”很多,也可以用属性定义和Fluent API混合起来使用;
以下的Fluent API定义了多对多的连接关系所采用的表名:
using EFTest.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions; namespace EFTest.DAL
{
public class SchoolContext : DbContext
{
public SchoolContext() : base("SchoolContext")
{
}
public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Course> Courses { get; set; }
public DbSet<Instructor> Instructors { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<OfficeAssignment> OfficeAssignments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Course>()
.HasMany(c => c.Instructors).WithMany(i => i.Courses)
.Map(t => t.MapLeftKey("CourseID")
.MapRightKey("InstructorID")
.ToTable("CourseInstructor"));
}
}
}
初始化种子数据
模型调整好后,在Migrations\Configuration.cs文件中Seed方法中放入测试种子数据:
namespace EFTest.Migrations
{
using DAL;
using Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<EFTest.DAL.SchoolContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
} protected override void Seed(EFTest.DAL.SchoolContext context)
{
var students = new List<Student>
{
new Student { FirstMidName = "Carson", LastName = "Alexander",
EnrollmentDate = DateTime.Parse("2010-09-01") },
new Student { FirstMidName = "Meredith", LastName = "Alonso",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Arturo", LastName = "Anand",
EnrollmentDate = DateTime.Parse("2013-09-01") },
new Student { FirstMidName = "Gytis", LastName = "Barzdukas",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Yan", LastName = "Li",
EnrollmentDate = DateTime.Parse("2012-09-01") },
new Student { FirstMidName = "Peggy", LastName = "Justice",
EnrollmentDate = DateTime.Parse("2011-09-01") },
new Student { FirstMidName = "Laura", LastName = "Norman",
EnrollmentDate = DateTime.Parse("2013-09-01") },
new Student { FirstMidName = "Nino", LastName = "Olivetto",
EnrollmentDate = DateTime.Parse("2005-09-01") }
}; students.ForEach(s => context.Students.AddOrUpdate(p => p.LastName, s));
context.SaveChanges(); var instructors = new List<Instructor>
{
new Instructor { FirstMidName = "Kim", LastName = "Abercrombie",
HireDate = DateTime.Parse("1995-03-11") },
new Instructor { FirstMidName = "Fadi", LastName = "Fakhouri",
HireDate = DateTime.Parse("2002-07-06") },
new Instructor { FirstMidName = "Roger", LastName = "Harui",
HireDate = DateTime.Parse("1998-07-01") },
new Instructor { FirstMidName = "Candace", LastName = "Kapoor",
HireDate = DateTime.Parse("2001-01-15") },
new Instructor { FirstMidName = "Roger", LastName = "Zheng",
HireDate = DateTime.Parse("2004-02-12") }
};
instructors.ForEach(s => context.Instructors.AddOrUpdate(p => p.LastName, s));
context.SaveChanges(); var departments = new List<Department>
{
new Department { Name = "English", Budget = ,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Abercrombie").ID },
new Department { Name = "Mathematics", Budget = ,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID },
new Department { Name = "Engineering", Budget = ,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Harui").ID },
new Department { Name = "Economics", Budget = ,
StartDate = DateTime.Parse("2007-09-01"),
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID }
};
departments.ForEach(s => context.Departments.AddOrUpdate(p => p.Name, s));
context.SaveChanges(); var courses = new List<Course>
{
new Course {CourseID = , Title = "Chemistry", Credits = ,
DepartmentID = departments.Single( s => s.Name == "Engineering").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = , Title = "Microeconomics", Credits = ,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = , Title = "Macroeconomics", Credits = ,
DepartmentID = departments.Single( s => s.Name == "Economics").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = , Title = "Calculus", Credits = ,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = , Title = "Trigonometry", Credits = ,
DepartmentID = departments.Single( s => s.Name == "Mathematics").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = , Title = "Composition", Credits = ,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID,
Instructors = new List<Instructor>()
},
new Course {CourseID = , Title = "Literature", Credits = ,
DepartmentID = departments.Single( s => s.Name == "English").DepartmentID,
Instructors = new List<Instructor>()
},
};
courses.ForEach(s => context.Courses.AddOrUpdate(p => p.CourseID, s));
context.SaveChanges(); var officeAssignments = new List<OfficeAssignment>
{
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Fakhouri").ID,
Location = "Smith 17" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Harui").ID,
Location = "Gowan 27" },
new OfficeAssignment {
InstructorID = instructors.Single( i => i.LastName == "Kapoor").ID,
Location = "Thompson 304" },
};
officeAssignments.ForEach(s => context.OfficeAssignments.AddOrUpdate(p => p.InstructorID, s));
context.SaveChanges(); AddOrUpdateInstructor(context, "Chemistry", "Kapoor");
AddOrUpdateInstructor(context, "Chemistry", "Harui");
AddOrUpdateInstructor(context, "Microeconomics", "Zheng");
AddOrUpdateInstructor(context, "Macroeconomics", "Zheng"); AddOrUpdateInstructor(context, "Calculus", "Fakhouri");
AddOrUpdateInstructor(context, "Trigonometry", "Harui");
AddOrUpdateInstructor(context, "Composition", "Abercrombie");
AddOrUpdateInstructor(context, "Literature", "Abercrombie"); context.SaveChanges(); var enrollments = new List<Enrollment>
{
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID,
Grade = Grade.A
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID,
Grade = Grade.C
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alexander").ID,
CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Alonso").ID,
CourseID = courses.Single(c => c.Title == "Composition" ).CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Anand").ID,
CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Barzdukas").ID,
CourseID = courses.Single(c => c.Title == "Chemistry").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Li").ID,
CourseID = courses.Single(c => c.Title == "Composition").CourseID,
Grade = Grade.B
},
new Enrollment {
StudentID = students.Single(s => s.LastName == "Justice").ID,
CourseID = courses.Single(c => c.Title == "Literature").CourseID,
Grade = Grade.B
}
}; foreach (Enrollment e in enrollments)
{
var enrollmentInDataBase = context.Enrollments.Where(
s =>
s.Student.ID == e.StudentID &&
s.Course.CourseID == e.CourseID).SingleOrDefault();
if (enrollmentInDataBase == null)
{
context.Enrollments.Add(e);
}
}
context.SaveChanges(); } void AddOrUpdateInstructor(SchoolContext context, string courseTitle, string instructorName)
{
var crs = context.Courses.SingleOrDefault(c => c.Title == courseTitle);
var inst = crs.Instructors.SingleOrDefault(i => i.LastName == instructorName);
if (inst == null)
crs.Instructors.Add(context.Instructors.Single(i => i.LastName == instructorName));
}
}
}
数据库迁移升级
在PM控制台输入: add-Migration ComplexDataModel
这个时候如果直接输入 update-database 会报错,那是因为Course这个表里已经有数据,如果直接加不可为空的列是会报错的;
所以需要在刚刚生成的带时间戳的 XXXXXXXXXXX_ComplexDataModel文件中如下面增加修改部分代码:
即先插入一条临时的Department ,然后把现在所有的Course数据行在增加Department列的时候,指向这个临时Department.
CreateTable(
"dbo.CourseInstructor",
c => new
{
CourseID = c.Int(nullable: false),
InstructorID = c.Int(nullable: false),
})
.PrimaryKey(t => new { t.CourseID, t.InstructorID })
.ForeignKey("dbo.Course", t => t.CourseID, cascadeDelete: true)
.ForeignKey("dbo.Instructor", t => t.InstructorID, cascadeDelete: true)
.Index(t => t.CourseID)
.Index(t => t.InstructorID); // Create a department for course to point to.
Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())");
// default value for FK points to department created above.
AddColumn("dbo.Course", "DepartmentID", c => c.Int(nullable: false, defaultValue: 1));
//AddColumn("dbo.Course", "DepartmentID", c => c.Int(nullable: false)); AlterColumn("dbo.Course", "Title", c => c.String(maxLength: ));
最后执行 update-database 即可。
EF6学习笔记(六) 创建复杂的数据模型的更多相关文章
- 【EF6学习笔记】目录
[EF6学习笔记](一)Code First 方式生成数据库及初始化数据库实际操作 [EF6学习笔记](二)操练 CRUD 增删改查 [EF6学习笔记](三)排序.过滤查询及分页 [EF6学习笔记]( ...
- ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)
个人从传统的CS应用开发(WPF)开始转向BS架构应用开发: 先是采用了最容易上手也是最容易搞不清楚状况的WebForm方式入手:到后面就直接抛弃了服务器控件的开发方式,转而采用 普通页面+Ajax+ ...
- EF6 学习笔记(五):数据库迁移及部署
EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 原文地址:Code First Migrations and Deployment 原文主要讲两部分:开发环境下 ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- EF6 学习笔记(二):操练 CRUD 增删改查
EF6学习笔记总目录 ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 接上篇: EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作 本篇原文链接: I ...
- EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作
EF6 学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习 ...
- Django:学习笔记(2)——创建第一个应用
Django:学习笔记(2)——创建第一个应用 创建应用 在 Django 中,每一个应用都是一个 Python 包,并且遵循着相同的约定.Django 自带一个工具,可以帮你生成应用的基础目录结构, ...
- 【opencv学习笔记六】图像的ROI区域选择与复制
图像的数据量还是比较大的,对整张图片进行处理会影响我们的处理效率,因此常常只对图像中我们需要的部分进行处理,也就是感兴趣区域ROI.今天我们来看一下如何设置图像的感兴趣区域ROI.以及对ROI区域图像 ...
- Spring Boot 学习笔记(六) 整合 RESTful 参数传递
Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...
随机推荐
- 199. Spring Boot JNDI:这是虾米?
[视频&交流平台] àSpringBoot视频:http://t.cn/R3QepWG à SpringCloud视频:http://t.cn/R3QeRZc à Spring Boot源 ...
- dubbo实现原理介绍
一.什么是dubbo Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合).从服务模型的角度来看, ...
- 杰克.多西 twitter创始人 必做清单和不必做清单
必做清单 活在当下 接受脆弱(Be vulnerable) 只喝柠檬水和红酒 每天 6 组下蹲和俯卧撑 每天跑步 3 英里 每天思考本清单 站直了 打拳击沙袋 10 分钟 跟所有人打招呼 每天 7 小 ...
- python 的包的导入
已经写过一篇包的导入了,最近又遇到了点问题,所以想把这些再搞的明白点就又试了试 代码结构如下 在test目录下,有Admin包,home包,在home下有它的子包foo 各个文件代码如下 admins ...
- dto vo
不过符合规矩的做法是DTO里可以放各种List<VO>,而VO和entity就是一一对应的关系,vo里不能放entity,entity里也不能放vo,vo和entity只存放和数据库完全相 ...
- 关于spfa
关于spfa的一些事宜.... 刚开始学的时候只会跑最短路,代码都是背下来的.以下是背的代码... inline void spfa(int s) { queue<int>q;q.push ...
- 2019/1/9 6系列所有装置编号与SIM卡信息抓取
一.报错:File "G:/station/6系列装置信息明细.py", line 12, in <module>workbook.save(r'.\6系列装置明细表. ...
- R语言-图的要素颜色
1.设置图形要素的颜色 Plot函数中,使用col=参数来决定要素的颜色 如果不指定plot type,颜色加在散点上,如果指定了plot type,例如line,则颜色加在线上 其它函数,例如bar ...
- php 二维数组按照某个键排序
$date = array_column($arr, 'run_date'); //上面得到的结果:array(0=>'2017-11-21',1=>'2017-11-20',3=> ...
- html2canvas
最近公司有个需求,实现html 页面元素转为png图像,这边用了html2canvas来实现.,这里记录一下,避免以后忘了~~ 官网链接: http://html2canvas.hertzen.com ...