mysql 表引擎 entity framework_EntityFramework之数据库以及表基本创建(一)
前言
之前有學(xué)過EF一段時間那時EF才4.0似乎還不太穩(wěn)定,而現(xiàn)在EF都已7.0版本,同時AspNet Identity都與此大有關(guān)聯(lián),看來是大勢所趨于是開始學(xué)習(xí)EF,在學(xué)EF過程中也遇到一些小問題,特此錄下,以備忘!
數(shù)據(jù)庫和表基本創(chuàng)建
為了更好的循序漸進(jìn)稍微概括下典型創(chuàng)建EF Code First過程(看之即懂,懂即略過)
第一步先定義兩個類,如下:
public classStudent
{publicStudent()
{
}public int StudentID { get; set; }public string StudentName { get; set; }
}public classStandard
{publicStandard()
{
}public int StandardId { get; set; }public string StandardName { get; set; }
}
第二步:繼承EF上下文DbContext
public classSchoolContext : DbContext
{
public SchoolContext():base("name=DBConnectionString"){
}public DbSet Students { get; set; }public DbSet Standards { get; set; }protected override voidOnModelCreating(DbModelBuilder modelBuilder)
{base.OnModelCreating(modelBuilder);
}
}
學(xué)生上下文中構(gòu)造函數(shù)中的name去讀取如下配置文件來命名數(shù)據(jù)庫名稱:?DBByConnectionString
然后在控制臺中通過EF上下文添加數(shù)據(jù)并保存,如下:
using (var ctx = newSchoolContext())
{
Student stud= new Student() { StudentName = "New Student"};
ctx.Students.Add(stud);
ctx.SaveChanges();
}
最終生成數(shù)據(jù)庫以及表如下圖:
上述創(chuàng)建數(shù)據(jù)庫的過程只需注意:可以手動通過添加構(gòu)造函數(shù)的name來命名數(shù)據(jù)庫名稱或者無需添加name那么生成的數(shù)據(jù)庫名稱是以上下文中的命名空間+上下文類來命名數(shù)據(jù)庫名稱。
數(shù)據(jù)庫創(chuàng)建以及表一勞永逸配置
下面創(chuàng)建方法是看過園友hystar(EF教程)而寫的,確實(shí)是好方法,就搬過來了,為什么說一勞永逸呢?不明白的話,可以去看看他的文章!首先添加兩個類Student(學(xué)生類)和Course(課程類)。
public classStudent
{public int ID { get; set; }public string Name { get; set; }public int Age { get; set; }public virtual Course Course { get; set; }
}public classCourse
{public int StudentID { get; set; }public string Name { get; set; }public virtual Student Student { get; set; }
}
添加EFDbContext類并繼承DbContext上下文,代碼如下:
public classEntityDbContext : DbContext
{publicEntityDbContext()
:base("name=test2")
{ }///
///通過反射一次性將表進(jìn)行映射///
///
protected override voidOnModelCreating(DbModelBuilder modelBuilder)
{var typesRegister =Assembly.GetExecutingAssembly().GetTypes()
.Where(type=> !(string.IsNullOrEmpty(type.Namespace))).Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));foreach (var type intypesRegister)
{
dynamic configurationInstance=Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
}
}
由于是手動命名數(shù)據(jù)庫名稱,當(dāng)然得讀取配置文件
上述配置要添加的數(shù)據(jù)庫建立在VS2013自帶的實(shí)例中!我們首先初始化數(shù)據(jù)庫看看:
EntityDbContext ctx = newEntityDbContext();
結(jié)果運(yùn)行就出現(xiàn)如下經(jīng)典錯誤:
在與SQLServer建立連接時出現(xiàn)與網(wǎng)絡(luò)相關(guān)的或特定與實(shí)例的錯誤.未找到或無法訪問服務(wù)器.請驗(yàn)證實(shí)例名稱是否正確并且SQL SERVER已配置允許遠(yuǎn)程鏈接provide:命名管道提供程序,error:40 -無法打開到SQL Server的連接)
那肯定是無法連接到?(localdb)\v11.0?,于是當(dāng)我在服務(wù)器打開添加連接中添加服務(wù)器名為?(localdb)\v11.0?時也是無法響應(yīng),連接不到!最終通過SqlLocalDB命令在Command Prompt(命令行)中輸入
SqlLocalDB.exe start v11.0
啟動該實(shí)例才算完事,主要原因是安裝了SQL 2012默認(rèn)啟動的實(shí)例該SQL 2012而VS 2013中的實(shí)例被停止運(yùn)行得手動啟動,如果要查看其信息來查看是否已經(jīng)啟動,通過以下命令即可:
SqlLocalDB.exe info v11.0
VS2013中默認(rèn)的實(shí)例應(yīng)該是(localdb)\v11.0,如果在服務(wù)器中添加連接輸入(localdb)\v11.0是錯誤的,你可以通過上述?SqlLocalDB.exe info v11.0?命令復(fù)制并添加如圖的字符串即可
似乎只要第一次啟動了,以后每次都會連接上,不會再出現(xiàn)如上問題!
上述中我們對于EF上下文不用每次都初始化數(shù)據(jù)庫,在EF中初始化數(shù)據(jù)庫有三種策略:
CreateDatabaseIfNotExists:該項也是默認(rèn)初始化數(shù)據(jù)庫的一項,要是數(shù)據(jù)庫不存在就創(chuàng)建數(shù)據(jù)庫。
DropCreateDatabaseIfModelChanges:只要數(shù)據(jù)模型發(fā)生了改變就重新創(chuàng)建數(shù)據(jù)庫。
DropCreateDatabaseAlways:只要每次初始化上下文時就創(chuàng)建數(shù)據(jù)庫。
鑒于此我們在EFDbContext中采用第二種策略。創(chuàng)建一個初始化類的策略?EFDbContextInit
///
///當(dāng)對象實(shí)體對象發(fā)生改變時重生創(chuàng)建數(shù)據(jù)庫///
public class EntityDbContextInit : DropCreateDatabaseIfModelChanges{protected override voidSeed(EntityDbContext context)
{base.Seed(context);
}
}
在EFDbContext靜態(tài)構(gòu)造函數(shù)中進(jìn)行初始化此方法:
staticEntityDbContext()
{
Database.SetInitializer(newEntityDbContextInit());
}
自此EFDbContext構(gòu)建完畢!下面就是模型映射了,我們假設(shè)學(xué)生和課程是1:1關(guān)系,則我們添加的兩個實(shí)體映射如下:
StudentMap(學(xué)生類實(shí)體映射)
public class StudentMap : EntityTypeConfiguration{publicStudentMap()
{
ToTable("Student");
HasKey(d=>d.ID);//HasRequired(p => p.Course).WithRequiredDependent(i => i.Student);//HasRequired(p => p.Course).WithOptional(i => i.Student);
HasRequired(p=> p.Course).WithRequiredPrincipal(p =>p.Student);
HasOptional(p=> p.Course).WithRequired(p =>p.Student);
/*
對于上述映射關(guān)系不太理解的話可以去上述給出鏈接文章。我只說明怎么去很好的理解這兩組的意思,第一組?WithRequiredDependent?和第二組
WithRequiredPrincipal?一個是Dependent是依賴的意思說明后面緊接著的Student是依賴對象,而前面的Course是主體,而Principal
首先的意思,說明后面緊接著的是Student是主體,而Course是依賴對象。很顯然在這個關(guān)系中課程是依賴學(xué)生的。所以映射選第二組
*/
}
}
CourseMap(課程類映射)
public class CourseMap : EntityTypeConfiguration{publicCourseMap()
{
ToTable("Course");
HasKey(p=>p.StudentID);
}
}
接下來我們進(jìn)行添加數(shù)據(jù)并保存通過如下代碼:
EntityDbContext ctx = newEntityDbContext();var s = newStudent()
{
Name= "1",
Age= 12,
Course= new Course() { Name = "12"}
};
ctx.Set().Add(s);
ctx.SaveChanges();
數(shù)據(jù)添加和保存都已通過,接下來進(jìn)行查詢數(shù)據(jù),查詢數(shù)據(jù)有兩種方式:
(1)直接通過EF中Set()方法獲得數(shù)據(jù)集合
(2)通過EF中SqlQuery()方法通過sql語句查詢
如要獲得上述學(xué)生數(shù)據(jù)列表集合,可以通過如下操作:
EntityDbContext ctx = newEntityDbContext();var list = ctx.Set().ToList();
或者
SqlParameter[] parameter={ };var list = ctx.Database.SqlQuery("select * from student", parameter);
于是我監(jiān)視下返回的list集合中的數(shù)據(jù)類型,如圖
oh,shit!和我們實(shí)際的實(shí)體類型不符,通過EF產(chǎn)生的卻是?DynamicProxies?,于是到Sytem.Data.Entity類下去看看是個什么類型,居然沒找到,估計看這單詞意思就是運(yùn)行時產(chǎn)生的動態(tài)代理對象。那么,你覺得是不是沒什么影響了???那影響可大了,請看下面操作:
var list = ctx.Set().ToList();var jsonString = JsonConvert.SerializeObject(list);
我嘗試將其序列化看看結(jié)果,一運(yùn)行,oh,no!錯誤如下:
這意思是檢測到在Course里面有Student屬性,而Student類里又有Course這就相當(dāng)于自己引用自己,導(dǎo)致了循環(huán)引用就成了死循環(huán)。(這就是因?yàn)?DynamicProxies?導(dǎo)致的結(jié)果)所以當(dāng)前要將其代理對象轉(zhuǎn)換為我們的實(shí)體對象即可。
則通過Select()方法投影將其代碼進(jìn)行改造后如下:
var list = ctx.Set().Include(p => p.Course).ToList().Select(entity => new Student() { ID = entity.ID, Name = entity.Name, Age =entity.Age }).ToList();
或者var list = ctx.Set().Include("Course").ToList().Select(entity => new Student() { ID = entity.ID, Name = entity.Name, Age = entity.Age }).ToList();
對象轉(zhuǎn)換成功,如下:
序列化成功結(jié)果如下:
【注意】你用EF獲得數(shù)據(jù)集合后得?ToList()?因?yàn)榇藭r集合對象為代理對象,否則進(jìn)行轉(zhuǎn)換將報錯,代碼如下:
var list = ctx.Set().Include(p => p.Course).Select(entity => new Student() { ID = entity.ID, Name = entity.Name, Age = entity.Age }).ToList();
報錯如下:
上述轉(zhuǎn)換也叫DTO(Data Transfer Objects)數(shù)據(jù)轉(zhuǎn)換為對象,像這種情況在EF中很常見。下面給出老外的用兩張圖在兩個常見的場景中來展現(xiàn)關(guān)于DTO的概念:
Getting Information: DAL=>BLL=>GUI
Insert Information: GUI=>BLL=>DAL
總結(jié)
(1)當(dāng)安裝了sql時則默認(rèn)啟動的是此實(shí)例,那么VS中的實(shí)例則會停止啟動,需要通過SqlLocalDB命令進(jìn)行啟動。
(2)通過EF獲得的數(shù)據(jù)集合對象為代理對象,需要先轉(zhuǎn)換為實(shí)體對象才能進(jìn)行序列化或者其他操作。
補(bǔ)充
在此感謝園友中華小鷹,經(jīng)其提示用上述一勞永逸配置無法配置復(fù)雜類型!
modelBuilder.Configurations.AddFromAssembly(Assembly.GetExecutingAssembly());
通過上述代碼既能配置實(shí)體類型也能配置復(fù)雜類型,用此方法更加精簡!當(dāng)然若你將復(fù)雜類型作為另一個類的導(dǎo)航屬性時上述代碼也是可以滿足所需的!
總結(jié)
以上是生活随笔為你收集整理的mysql 表引擎 entity framework_EntityFramework之数据库以及表基本创建(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java hive查询,hive查询报错
- 下一篇: mysql报错级别_MySQL启动出现几