問題描述
我想為想要從 linq2sql 遷移到 linq2entities 和 ADO.net 實體框架(此處稱為 L2E)的人們提供參考.我不想討論這兩個哪個更好.我只想為想要從一個過渡到另一個的人創(chuàng)建一個列表,列出這兩者之間的差異.
I'd like to start a reference for people who want to move from linq2sql to linq2entities and the ADO.net Entity Framework (in here called L2E). I don't want to discuss which of these two is better. I just want to create a list of differences between these two for people who want to transition from one to the other.
基本的東西很簡單:刪除 linq2sql 數(shù)據(jù)類,添加 ado.net 模型(從數(shù)據(jù)庫創(chuàng)建).將實體"重命名為之前數(shù)據(jù)上下文的名稱.
The basic stuff is easy: remove the linq2sql data classes, add ado.net model (created from database). Rename 'Entities' to the name of the former datacontext.
現(xiàn)在,差異.例如,為了在 L2S 中持久化(保存)更改,我會使用:
using (MyDataClassesDataContext mydc = new MyDataClassesDataContext())
{
// change data
mydc.SubmitChanges();
}
在 L2E 中,這必須更改為:
In L2E this would have to be changed to:
using (MyDataClassesDataContext mydc = new MyDataClassesDataContext())
{
// change data
mydc.SaveChanges();
}
第二個示例,要在 L2S 中插入新記錄,您可以使用:
using (MyDataClassesDataContext mydc = new MyDataClassesDataContext())
{
MyTable myRow = new MyTable();
mydc.MyTable.InsertOnSubmit(myRow);
mydc.SubmitChanges();
}
在 L2E 中,這必須更改為:
In L2E this would have to be changed to:
using (MyDataClassesDataContext mydc = new MyDataClassesDataContext())
{
MyTable myRow = new MyTable(); // or = MyTable.CreateMyTable(...);
mydc.AddToMyTable(myRow);
mydc.SaveChanges();
}
對于其他代碼片段,我將跳過 using (...) 部分和 SubmitChanges/SaveChanges,因為它每次都是相同的.
要將更改的對象附加到 L2S 中的數(shù)據(jù)上下文/模型(使用時間戳):
mydc.MyTable.Attach(myRow);
在 L2E 中:
// you can use either
mydc.Attach(myRow);
// or (have not tested this)
mydc.AttachTo("MyTable", myRow);
要將更改的對象附加到 L2S 中的數(shù)據(jù)上下文/模型(使用原始對象):
mydc.MyTable.Attach(myRow, myOriginalRow);
在 L2E 中(MSDN - 應用對分離對象所做的更改):
mydc.Attach(myOriginalRow);
mydc.ApplyPropertyChanges(myOriginalRow.EntityKey.EntitySetName, myRow);
要刪除 L2S 中的記錄:
mydc.MyTable.DeleteOnSubmit(myRow);
在 L2E 中:
mydc.DeleteObject(myRow);
要顯示已創(chuàng)建的用于 L2S 調(diào)試的 SQL 命令:
mydc.Log = Console.Out;
// before mydc.SubmitChanges();
在 L2E 中,您可以顯示查詢的 SQL(感謝 TFD):
In L2E you can show the SQL for a query (thanks to TFD):
using System.Data.Objects;
...
var sqlQuery = query as ObjectQuery;
var sqlTrace = sqlQuery.ToTraceString();
遺憾的是,我發(fā)現(xiàn)無法輸出為調(diào)用 SaveChanges() 生成的 SQL - 您需要使用 用于此目的的 SQL 分析器.
Sadly, I found no way to output the SQL generated for a call to SaveChanges() - you'd need to use a SQL profiler for this.
為了如果不存在 L2S,則從該方案創(chuàng)建一個數(shù)據(jù)庫:
if (!mydc.DatabaseExists())
mydc.CreateDatabase();
在 L2E 中:
// according to TFD there are no DDL commands in L2E
要在 L2S 中對數(shù)據(jù)庫執(zhí)行 SQL 命令:
mydc.ExecuteCommand("ALTER TABLE dbo.MyTable ADD CONSTRAINT DF_MyTable_ID DEFAULT (newid()) FOR MyTableID");
在 L2E 中:
要對 EF 中的數(shù)據(jù)庫執(zhí)行 eSQL 命令(請注意,eSQL 尚不支持 DDL 或 DML(更改、插入、更新、刪除)命令):
To execute an eSQL command against the database in EF (beware, eSQL does not support DDL or DML (alter, Insert, update, delete) commands yet):
using System.Data.EntityClient;
...
EntityConnection conn = this.Connection as EntityConnection;
using (EntityCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = @"Select t.MyValue From MyEntities.MyTable As t";
var result = cmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess);
result.Read();
var myValue = result.GetValue(0);
...
conn.Close();
}
命令文本在 Entity SQL 中,與 T-SQL 不是 100% 相同.
(感謝 TFD)
The command text is in Entity SQL which is not 100% the same as T-SQL.
(thanks to TFD)
如果您需要在同一連接上使用 DDL/DML 命令,您可能需要自己創(chuàng)建數(shù)據(jù)庫連接,使用您自制的 db 連接連接 EF,并將此連接用于您的 DML 命令.不漂亮,自己看看:
If you need DDL/DML commands on the same connection, you might need to create the database connection yourself, connect the EF using your selfmade db connection, and use this connection for your DML commands. Not pretty, have a look for yourself:
MetadataWorkspace workspace = new MetadataWorkspace(new string[] { "res://*/" }, new Assembly[] { Assembly.GetExecutingAssembly() });
using (SqlConnection sqlConnection = new SqlConnection("Data Source=salsa;Initial Catalog=SamAlyza;Integrated Security=True"))
using (EntityConnection econ = new EntityConnection(workspace, sqlConnection))
using (AlyzaDataClassesDataContext adc = new AlyzaDataClassesDataContext(econ))
{
// now you can use the SqlConnection like always
}
提供新創(chuàng)建的 L2S-Class 的默認值 覆蓋部分方法 OnCreated:
To provide default values for a newly created L2S-Class override the partial method OnCreated:
partial void OnCreated()
{
Name = "";
}
在 L2E 中,你可以為你的表類創(chuàng)建一個默認的構(gòu)造函數(shù):
In L2E you can just create a default constructor for your table class:
partial class MyTable
{
public MyTable()
{
Name = "";
}
}
以下示例是關(guān)于兩個表之間的 1:n 關(guān)系.我在這里用 SQL 定義了表,所以你知道我在寫什么:
The following examples are about a 1:n relation between two tables. I define the table here in SQL, so you know what I'm writing about:
CREATE TABLE dbo.[MyTable]
(
[MyTableID] uniqueidentifier NOT NULL ROWGUIDCOL CONSTRAINT [PK_MyTable] PRIMARY KEY,
[Name] nvarchar(100) NOT NULL,
) ON [PRIMARY]
ALTER TABLE dbo.[MyTable] ADD CONSTRAINT [DF_MyTable_ID] DEFAULT (newid()) FOR [MyTableID]
CREATE TABLE dbo.[MySubTable]
(
[MySubTableID] uniqueidentifier NOT NULL ROWGUIDCOL CONSTRAINT [PK_MySubTable] PRIMARY KEY,
[MyTableID] uniqueidentifier NULL,
[Subname] decimal(18,2) NOT NULL,
) ON [PRIMARY]
ALTER TABLE dbo.[MySubTable] ADD CONSTRAINT [DF_MySubTable_ID] DEFAULT (newid()) FOR [MySubTableID]
ALTER TABLE dbo.[MySubTable] ADD CONSTRAINT [FK_MySubTable_MyTable] FOREIGN KEY
(
[MyTableID]
) REFERENCES dbo.[MyTable]
(
[MyTableID]
) ON DELETE CASCADE
將一條記錄插入到 MyTable 中,并在 L2S 中插入相應的 MySubTable:
MyTable myRow = new MyTable();
myRow.MySubTable.Add(new MySubTable());
mydc.MyTable.InsertOnSubmit(myRow);
在 L2E 中非常相似:
Very similar in L2E:
MyTable myRow = new MyTable();
myRow.MySubTable.Add(new MySubTable());
mydc.AddToSaLyWebsites(test);
在 L2S 中在子表中搜索?/strong>,您可以使用:
In L2S to search in a subtable, you could use:
from u in adc.MySubTable
where u.MyTableID == _searchForTableID && u.Name == _searchForName
select u
在 L2E 中,您無法訪問關(guān)系列:
In L2E you can't access the relation columns:
from u in adc.MySubTable
where u.MyTable.MyTableID == _searchForTableID && u.Name == _searchForName
select u
(當然你也可以用)
from u in _searchForTable.MySubTable
where u.Name == _searchForName
select u
(奇怪的旁注:_searchForTable 不需要附加到 EF 才能工作.)
(strange side note: _searchForTable does not need to be attached to the EF for this to work.)
其他注意事項:
在 L2S 中,我可以在 LINQ 中使用其他功能.如果我在 L2E 中使用自定義函數(shù),我會得到一個不支持異常.所以,而不是
In L2S I can use miscellanous functions in LINQ. If I use custom functions in L2E I get a NotSupportedException. So, instead of
from t in mydc.MyTable
where t.Date >= _searchForDate && t.Date <= _searchForDate.AddHours(2)
select t;
在 L2E 中需要使用
In L2E one would need to use
DateTime endDate = _searchForDate.AddHours(2);
from t in mydc.MyTable
where t.Date >= _searchForDate && t.Date <= endDate
select t;
雖然 L2S 可以從數(shù)據(jù)庫中讀取自動生成的值,例如自動生成的 ID,但在 L2E 中,這似乎只能使用 sql 類型標識.
While L2S can read autogenerated values from the database, like, for example the autogenerated ID, in L2E this seems to only work using sql type identity.
(當我偶然發(fā)現(xiàn)它們時,或者有人在答案中添加它們時,我會在這篇文章中收集更多差異)
(I'll collect more differences in this post as I stumble upon them, or as someone adds them in answers)
一些鏈接,也許有用:
- Transact-SQL 和 Entity-SQL 的區(qū)別
- NET - ADO.NET Entity Framework &LINQ 到實體
- Mike Taulty 關(guān)于斷開連接的 LINQ to Entities(測試版 2L2E)
推薦答案
在 EF 中顯示創(chuàng)建的用于調(diào)試的 SQL 命令
To show the created SQL commands for debugging in EF
using System.Data.Objects;
...
var sqlQuery = query as ObjectQuery<T>;
var sqlTrace = sqlQuery.ToTraceString();
AFAIK 沒有創(chuàng)建數(shù)據(jù)庫或執(zhí)行任何類型的 DDL 工作的命令.這是Entity SQL"語言的設(shè)計限制
AFAIK there are no commands to create DB's or do any sort of DDL work. This is design limitation of the "Entity SQL" language
EDMX 設(shè)計圖面將映射您當前的數(shù)據(jù)庫架構(gòu),而不是相反
The EDMX design surface will map your current database schema, not the other way around
這篇關(guān)于如何從 Linq 2 SQL 遷移到 Linq 2 實體?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!