A. 如何使用CodeFirst進行數據遷移
如果你還在為
支持xxx上下文的模型已在資料庫創建後發生更改。請考慮使用 Code First 遷移更新資料庫
找到你的資料庫上下文所在的類庫(一般都是寫在項目中的model中,也有的獨立model類庫)
打開Nuget 程序包管理控制台
輸入:Enable-Migrations 回車
如果正確的話 則顯示已為項目 xxx啟用 Code First 遷移。
我在這里說下 幾種有可能出現的錯誤:
1.No context type was found in the assembly xxx
在當前項目中 沒有找到資料庫上下文,也就是DbContext 繼承的的 "資料庫.cs"
2.The EntityFramework package is not installed on project xxx
當前項目已經找到了數據上下文,但是沒有EntityFrameWork 需要安裝輸入 install-package entityframework(手大的 不知道對不對)
基本就這兩個問題,如果安裝成功則在項目中 出現Migrations文件夾,裡面會記錄每次數據遷移所發生的變化。
非常好用,不用再刪除資料庫 重新生成 數據丟失等問題。
常用語句 :enable-Migrations -Force 替換遷移數據文件 update-database 更新 add-migration 添加新的更新文件
B. EF中的code first模式 怎麼創建資料庫
方法/步驟
1
EF的Code First模式不需要我們創建什麼數據向導,直接寫代碼就行了。我們用NET最簡單的控制台應用程序來說明。如下圖所示
7
通過以上的步驟,你感覺到EF的Code First模式的魅力了沒,自動創建資料庫以及表。這也是現在應用最多的模式了,好了,這次分享就到這里。有什麼問題的話,留言咨詢即可。
C. MVC4+EFcodefirst中如何處理資料庫歷史記錄的保存和查詢
二、查詢問題分析
(一) 數據查詢應該在哪做
在EF中,面向對象的數據查詢主要提供了兩種方式:
TEntity DbSet<TEntity>.Find(params object[] keyValues):針對主鍵設計的通過主鍵查找單個實體,會先在EF的本地數據集Local中進行查詢,如果沒有,再去資料庫中查詢。
IQueryable<T>、IEnumerable<T>類型的所有數據查詢的擴展方法(由於DbSet<T>繼承於IQueryable<T>與IEnumerable<T>),如SingleOrDefault,FirstOrDefault,Where等。其中IQueryable<T>的擴展方法會先收集需求,到最後一步再生成相應的SQL語句進行數據查詢;而IEnumerable<T>的擴展方法則是在查詢的第一步就生成相應的SQL語句獲取數據到內存中,後面的操作都是以內存中的數據為基礎進行操作的。
以上兩種方式為EF的數據查詢提供了極大的自由度,這個自由度是我們在封裝的時候需要保持的。但是,在閱讀不少人(其中不乏工作了幾年的)對EF的封裝,設計統一的數據操作介面Repository中關於數據查詢的操作中,通常會犯如下幾種失誤:
設計了很多GetByName,GetByXX,GetByXXX的操作,這些操作通常並不是所有實體都會用到,只是部分實體的部分業務用到,或者是「估計會用到」。
定義了按條件查詢的SingleOrDefault,FirstOrDefault,Count,GetByPredicate(predicate)等方法,但是對於條件predicate的類型是使用Expression<Func<TEntity, boo>>還是Func<TEntity, bool>很糾結,最後乾脆兩個都設計,相當於把IQueryable<T>,IEnumerable<T>的方法再過一遍。
定義了獲取全部數據的GetAll()方法,但卻使用了IEnumerable<TEntity>類型的返回值,明白的同學都知道,這相當於把整個表的數據都載入到內存中,問題很嚴重,設計者卻不知道。
諸如此類,各種奇葩的查詢操作層出不窮,這些操作或者破壞了EF數據查詢原有的靈活性,或者畫蛇添足。
其實,這么多失誤的原因只有一個,設計者忘記了EF是ORM,把EF當作ado.net來使用了。只要記著EF是ORM,以上這些功能已經實現了,就不要去重復實現了。那麼以上的問題就非常好解決了,只要:
在數據操作Repository介面中把EF的DbSet<TEntity>開放成一個只讀的IQueryable<TEntity>類型的屬性提供給業務層作為數據查詢的數據源
就可以了。這個數據源是只讀的,並且類型是IQueryable<T>,就保證了它只能作為數據查詢的數據源,而不像開放了DbSet<T>類型那樣可以在業務層中調用EF的內部方法進行增、刪、改等操作。另外IQueryable<T>類型保持了EF原有的查詢自由性與靈活性,簡單明了。這個數據集還可以傳遞到業務層的各個層次,以實現在哪需要數據就在哪查的靈活性。
(二) 循環中的查詢陷阱
EF的導航屬性是延遲載入的,延遲載入的優點就是不用到不載入,一次只載入必要的數據,這減少了每次載入的數據量,但缺點也不言自明:極大的增加了資料庫連接的次數,比如如下這么個簡單的需求:
輸出每個用戶擁有的角色數量
根據這個需求,很容易就寫出了如下的代碼:
遍歷所有用戶信息,輸出每個用戶信息中角色(導航屬性)的數量。
上面這段代碼邏輯很清晰,看似沒有什麼問題。我們來分析一下代碼的執行過程:
132行,從IOC容器中獲取用戶倉儲介面的實例,這沒什麼問題。
133行,取出所有用戶信息(memberRepository.Entities),執行SQL如下:
SELECT [Extent1].[Id] AS [Id], [Extent1].[UserName] AS [UserName], [Extent1].[Password] AS [Password], [Extent1].[NickName] AS [NickName], [Extent1].[Email] AS [Email], [Extent1].[IsDeleted] AS [IsDeleted], [Extent1].[AddDate] AS [AddDate], [Extent1].[Timestamp] AS [Timestamp], [Extent2].[Id] AS [Id1] FROM [dbo].[Members] AS [Extent1] LEFT OUTER JOIN [dbo].[MemberExtends] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Member_Id]
雖然EF生成的SQL有些復雜,但還是沒什麼問題
3. 136行,就開始有問題了,每次循環都會連接一次資料庫,執行一次如下查詢(最後一個1是用戶編號):
exec sp_executesql N'SELECT [Extent2].[Id] AS [Id], [Extent2].[Name] AS [Name], [Extent2].[Description] AS [Description], [Extent2].[RoleTypeNum] AS [RoleTypeNum], [Extent2].[IsDeleted] AS [IsDeleted], [Extent2].[AddDate] AS [AddDate], [Extent2].[Timestamp] AS [Timestamp] FROM [dbo].[RoleMembers] AS [Extent1] INNER JOIN [dbo].[Roles] AS [Extent2] ON [Extent1].[Role_Id] = [Extent2].[Id] WHERE [Extent1].[Member_Id] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
試想,如果有100個用戶,就要連接100次資料庫,這么一個簡單的需求,連接了101次資料庫,還不得讓資料庫瘋掉了。
當然,有同學可以要說,這里用了延遲載入才會多了很多連接資料庫的次數,你可以立即載入啊,把Role角色一次性載入進來。好吧,我們來看看立即載入:
143行,在取所有用戶信息的時候使用Include方法把與用戶關聯的所有角色信息也一並查詢出來了,這樣在循環遍歷的時候就不會再連接資料庫去查詢角色信息了。但是如果看到執行的SQL語句,估計你想死的心情都有了。執行的查詢如下:
SELECT [Project1].[Id] AS [Id], [Project1].[UserName] AS [UserName], [Project1].[Password] AS [Password], [Project1].[NickName] AS [NickName], [Project1].[Email] AS [Email], [Project1].[IsDeleted] AS [IsDeleted], [Project1].[AddDate] AS [AddDate], [Project1].[Timestamp] AS [Timestamp], [Project1].[Id1] AS [Id1], [Project1].[C1] AS [C1], [Project1].[Id2] AS [Id2], [Project1].[Name] AS [Name], [Project1].[Description] AS [Description], [Project1].[RoleTypeNum] AS [RoleTypeNum], [Project1].[IsDeleted1] AS [IsDeleted1], [Project1].[AddDate1] AS [AddDate1], [Project1].[Timestamp1] AS [Timestamp1] FROM ( SELECT [Extent1].[Id] AS [Id], [Extent1].[UserName] AS [UserName], [Extent1].[Password] AS [Password], [Extent1].[NickName] AS [NickName], [Extent1].[Email] AS [Email], [Extent1].[IsDeleted] AS [IsDeleted], [Extent1].[AddDate] AS [AddDate], [Extent1].[Timestamp] AS [Timestamp], [Extent2].[Id] AS [Id1], [Join2].[Id] AS [Id2], [Join2].[Name] AS [Name], [Join2].[Description] AS [Description], [Join2].[RoleTypeNum] AS [RoleTypeNum], [Join2].[IsDeleted] AS [IsDeleted1], [Join2].[AddDate] AS [AddDate1], [Join2].[Timestamp] AS [Timestamp1], CASE WHEN ([Join2].[Member_Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] FROM [dbo].[Members] AS [Extent1] LEFT OUTER JOIN [dbo].[MemberExtends] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Member_Id] LEFT OUTER JOIN (SELECT [Extent3].[Member_Id] AS [Member_Id], [Extent4].[Id] AS [Id], [Extent4].[Name] AS [Name], [Extent4].[Description] AS [Description], [Extent4].[RoleTypeNum] AS [RoleTypeNum], [Extent4].[IsDeleted] AS [IsDeleted], [Extent4].[AddDate] AS [AddDate], [Extent4].[Timestamp] AS [Timestamp] FROM [dbo].[RoleMembers] AS [Extent3] INNER JOIN [dbo].[Roles] AS [Extent4] ON [Extent4].[Id] = [Extent3].[Role_Id] ) AS [Join2] ON [Extent1].[Id] = [Join2].[Member_Id] ) AS [Project1] ORDER BY [Project1].[Id] ASC, [Project1].[Id1] ASC, [Project1].[C1] ASC
(三) 導航屬性的查詢陷阱
我們再來回顧一下導航屬性的長相(以用戶信息中的角色信息為例):
可以看到,集合類的導航屬性是一個ICollection<T>類型的集合,其實現類可以是通常使用List<T>或者HashSet<T>。用了ICollection<T>,就限定了集合類的導航屬性是一個內存集合,只要用到這個導航屬性,就必須把集合中的所有數據都載入到內存中,才能進行後續操作。比如上面的例子中,我們的需求只是想知道用戶擁有角色的數量,原意只是要執行一下SQL的Count語句即可,卻想不到EF是把這個集合載入到內存中(上面的語句,是把當前用戶的所有角色信息查詢出來),再在內存中進行計數,這無形中是一個很大的資源浪費。比如在一個商城系統中,我們想了解一種商品的銷量(proct.Orders.Count),那就可能把幾萬條訂單信息都載入到內存中,再進行計數,這將是災難性的資源消耗。
D. dbfirst和codefirst有什麼區別
先分別介紹一下三種方法的聯系:
1.Database First是基於已存在的資料庫,利用某些工具(如VS提供的EF設計器)創建實體類,資料庫對象與實體類的匹配關系等,你也可以手動修改這些自動生成的代碼及匹配文件。也就是從一個資料庫開始,然後生成實體框架和相應代碼。
2.Model First 是先利用某些工具(如VS的EF設計器)設計出可視化的實體數據模型及他們之間的關系,然後再根據這些實體、關系去生成資料庫對象及相關代碼文件。
3.Code First 這種方式需要先寫一些代碼,如實體對象,數據關系等,然後根據已有的代碼描述,自動創建數據對象。但其實這種方法與Model First是非常類似的。我們自己寫的代碼,其實就是用代碼表示實體模型,而Model First是用可視化的方式描述了實體模型。
下面分析這三種方式的優缺點:
Database-First模式明顯性能會差點,但是它很適合初學者,或者是比較急的小型項目。還有一點,我們在做項目時可能不容易體會到它的好處,但如果做資料庫結構比較成熟穩定的產品時,我們可以很輕松的使用資料庫生成實體模型,從而實現快速開發。
Model-First模式優點是開發人員能夠在模型設計完成後,可以利用VS等工具快速生成資料庫腳本。缺點是設計模型時完全了解資料庫的結構,在模型中手動添加表關系,並且生成的腳本有點不簡潔。
Code-First模式優點是性能比較好,且代碼較少冗餘。不過它的缺點也有很多,由於都是代碼編寫的,比如更新資料庫。
這三種方式各有利弊,使用過程中我們要按實際需求來選擇。這些工具的出現和使用,大大提高了開發人員的開發速度,使得資料庫、模型等出現了復用、擴展的可能,在應對變化方面也做了足夠的工作。這些工具所體現的服務思想更提醒我們要全方位去考慮問題,在產品中做好應對變化的措施。
E. MVC中EF框架下CodeFirst事務處理,從表數據是根據主表主鍵添加,而主表主鍵是自動編號
EF Code-Frist本身就是支持事務的。
我們的每一次SaveChanges就是一個事務操作,只需要在所有更改都完成後,調用這個方法就可以了。
如果你不願意,網上還有人給出了手動的開啟事務的代碼(我沒有測試過):
DbConnection con = ((IObjectContextAdapter)ctx).ObjectContext.Connection;
con.Open();
using (var tran = con.BeginTransaction())
{
// 這里才是事務中的代碼
tran.Commit();
}
con.Close();
以上都是針對一個DbContext,也就是一個資料庫的時候,如果操作涉及到多個資料庫,還是使用分布式事務操作比較靠譜。
原文鏈接:http://www.cnblogs.com/youring2/archive/2012/05/23/2514962.html
F. EF code first 怎樣創建資料庫視圖
1. 使用CodeFirst方式創建資料庫
我們新建一個控制台項目,項目中添加兩個Model:Author和Blog以及DbContext。 DbContext的添加方式如下:
項目上右鍵->添加->新建項->ADO.NET Entity Data Model->Empty Code First model
項目代碼如下:
1 //默認生成的數據表名為類名+字母s,這里使用TableAttribute來指定數據表名為T_Authors
2 [Table("T_Authors")]
3 public class Author
4 {
5 public int Id { set; get; }
6 public string Name { set; get; }
7 /*
8 此處定義了Blog類型的屬性,所以要確保Blog類中至少要有一個表示主鍵的欄位,即public int Id { set; get; }。
否則在生成數據表時會報錯:"EntityType 'Blog' has no key defined. Define the key for this EntityType.
9 Blogs: EntityType: EntitySet 'Blogs' is based on type 'Blog' that has no keys defined."
10 */
11 public virtual ICollection<Blog> Blogs { set; get; }
12 }
13
14 [Table("T_Blogs")]
15 public class Blog
16 {
17 public int Id { set; get; }
18 public string Title { set; get; }
19 public DateTime Time { set; get; }
20 public int AuthorId { set; get; }
21 public virtual Author Author { set; get; }
22 }
23
24 public class MyDbContext: DbContext
25 {
26 public MyDbContext()
27 : base("name=MyDbContext")
28 {
29 }
30 //DbContext會根據配置文件中connectionStrings指定的資料庫名稱來建立資料庫
31 //DbContext根據DbSet屬性的類型來創建數據表,這里指定了Author類型的屬性,所以會生成T_Authors數據表
32 public virtual DbSet<Author> Authors { set; get; }
33 }
CodeFirst方式會根據配置文件中的配置生成資料庫,這里小編使用的是MYSQL資料庫,配置文件如下:
1 <!--EF for MYSQL-->
2 <entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">
3 <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
4 <providers>
5 <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
6 </providers>
7 </entityFramework>
8 <connectionStrings>
9 <add name="MyDbContext" connectionString="server=localhost;port=3306;database=EF;uid=root;password=root" providerName="System.Data.MySqlClient" />
10 </connectionStrings>
PS:小編使用的是EF6和MYSQL資料庫,所以要在項目中添加對Mysql.Data.Entity.EF6以及EntityFrameword 6.0的引用。
到此,我們已經完成生成資料庫的工作,接下來在Main方法中寫兩行代碼:
1 using (var db = new ManagerDb())
2 {
3 db.Authors.Add(new Author() { Name = "xfh" });
4 db.SaveChanges();
5 }
G. ASP.NET MVC的code first資料庫與SQL資料庫有什麼不同
Code First是Entity Framework提供的一種新的編程模型。通過Code First我們可以在還沒有建立資料庫的情況下就開始編碼,然後通過代碼來生成資料庫。
SQL資料庫即SQLServer數據,SQL Server 是Microsoft 公司推出的關系型資料庫管理系統。具有使用方便可伸縮性好與相關軟體集成程度高等優點,可跨越從運行Microsoft Windows 98 的膝上型電腦到運行Microsoft Windows 2012 的大型多處理器的伺服器等多種平台使用。
H. 什麼是代碼優先(Code First)求大神指導啊。
CodeFirst是EntityFramework的一種技術手段,因為傳統編程方式都是先建立資料庫,然後根據資料庫模型為應用程序建模,再進行開發;CodeFirst從字面上理解就是代碼先行,先在程序中建立要映射到資料庫的實體結構,然後EntityFramework可以根據實體結構生成所對應的資料庫。
I. EF通過資料庫生成code first實體,資料庫中不添加外鍵關系,實體類中如何配置關聯關系
你是想資料庫不要外鍵 但是實體要導航屬性吧
需求蠻奇特的
你實體也不加導航屬性 需要關聯數據的時候用 JOIN 查詢
重新EF介面 在生成資料庫的時候 只解釋生成關系