如何从Linq 2 SQL移动到Linq 2实体?

我想为想从linq2sql转换到linq2entities和ADO.netentity framework(在这里称为L2E)的人开始一个参考。 我不想讨论哪一个更好。 我只是想为这两个人想要从一个过渡到另一个创build一个差异列表。

基本的东西很简单:删除linq2sql数据类,添加ado.net模型(从数据库创build)。 将“实体”重命名为以前的datacontext的名称。


现在,差异。 例如, 要坚持(保存)在L2S中的变化,我会使用:

using (MyDataClassesDataContext mydc = new MyDataClassesDataContext()) { // change data mydc.SubmitChanges(); } 

在L2E中,这将不得不改为:

 using (MyDataClassesDataContext mydc = new MyDataClassesDataContext()) { // change data mydc.SaveChanges(); } 

第二个例子, 在L2S中插入一个新的logging,你可以使用:

 using (MyDataClassesDataContext mydc = new MyDataClassesDataContext()) { MyTable myRow = new MyTable(); mydc.MyTable.InsertOnSubmit(myRow); mydc.SubmitChanges(); } 

在L2E中,这将不得不改为:

 using (MyDataClassesDataContext mydc = new MyDataClassesDataContext()) { MyTable myRow = new MyTable(); // or = MyTable.CreateMyTable(...); mydc.AddToMyTable(myRow); mydc.SaveChanges(); } 

对于其他代码片段,我将跳过使用(…)部分和SubmitChanges / SaveChanges,因为它每次都是一样的。
将更改的对象附加到L2S中的datacontext / model (使用时间戳):

 mydc.MyTable.Attach(myRow); 

在L2E:

 // you can use either mydc.Attach(myRow); // or (have not tested this) mydc.AttachTo("MyTable", myRow); 

将更改的对象附加到L2S中的datacontext / model(使用原始对象)

 mydc.MyTable.Attach(myRow, myOriginalRow); 

在L2E中( MSDN – 将更改应用到分离的对象 ):

 mydc.Attach(myOriginalRow); mydc.ApplyPropertyChanges(myOriginalRow.EntityKey.EntitySetName, myRow); 

删除L2S中的logging

 mydc.MyTable.DeleteOnSubmit(myRow); 

在L2E:

 mydc.DeleteObject(myRow); 

在L2S中显示创build的用于debugging的SQL命令

 mydc.Log = Console.Out; // before mydc.SubmitChanges(); 

在L2E中,您可以显示查询的SQL (感谢TFD):

 using System.Data.Objects; ... var sqlQuery = query as ObjectQuery; var sqlTrace = sqlQuery.ToTraceString(); 

可悲的是,我发现没有办法输出生成的调用SaveChanges() 的SQL – 你需要使用SQL分析器 。


如果不存在,则从scheme创build数据库L2S

 if (!mydc.DatabaseExists()) mydc.CreateDatabase(); 

在L2E:

 // according to TFD there are no DDL commands in L2E 

在L2S中对数据库执行SQL命令

 mydc.ExecuteCommand("ALTER TABLE dbo.MyTable ADD CONSTRAINT DF_MyTable_ID DEFAULT (newid()) FOR MyTableID"); 

在L2E:

要在EF中执行针对数据库的eSQL命令(请注意,eSQL不支持DDL或DML(更改,插入,更新,删除)命令):

 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(); } 

命令文本在实体SQL中,与T-SQL不是100%相同的。
(感谢TFD)

如果在同一连接上需要DDL / DML命令,则可能需要自己创build数据库连接,使用自制db连接来连接EF,然后将此连接用于DML命令。 不漂亮,看看你自己:

 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 } 

新创build的L2S-Class提供默认值覆盖部分方法OnCreated:

 partial void OnCreated() { Name = ""; } 

在L2E中,您可以为您的表类创build一个默认的构造函数:

 partial class MyTable { public MyTable() { Name = ""; } } 

以下示例是关于两个表之间的1:n关系的。 我在SQL中定义表格,所以你知道我在写什么:

 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 

在L2S中使用相应的MySubTablelogging插入到MyTable中

  MyTable myRow = new MyTable(); myRow.MySubTable.Add(new MySubTable()); mydc.MyTable.InsertOnSubmit(myRow); 

L2E非常相似:

  MyTable myRow = new MyTable(); myRow.MySubTable.Add(new MySubTable()); mydc.AddToSaLyWebsites(test); 

在L2S 中search一个子表 ,你可以使用:

 from u in adc.MySubTable where u.MyTableID == _searchForTableID && u.Name == _searchForName select u 

在L2E中,您无法访问关系列:

 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这个工作。)


杂质说明:

在L2S中,我可以在LINQ中使用miscellanous函数。 如果我在L2E中使用自定义函数,我得到一个NotSupportedException。 所以,而不是

 from t in mydc.MyTable where t.Date >= _searchForDate && t.Date <= _searchForDate.AddHours(2) select t; 

在L2E中需要使用

 DateTime endDate = _searchForDate.AddHours(2); from t in mydc.MyTable where t.Date >= _searchForDate && t.Date <= endDate select t; 

虽然L2S可以从数据库读取自动生成的值,例如L2E中的自动生成的ID,但这似乎只能使用sqltypes标识。

(当我绊倒他们时,我会在这篇文章中收集更多的差异,或者当有人加上他们的答案时)

一些链接,也许有帮助:
– Transact-SQL和Entity-SQL的区别
– NET – ADO.NETentity framework和LINQ to Entities
– Mike Taulty关于LINQ to Entities断开连接(针对L2E的testing版2)

在EF中显示创build的用于debugging的SQL命令

 using System.Data.Objects; ... var sqlQuery = query as ObjectQuery<T>; var sqlTrace = sqlQuery.ToTraceString(); 

AFAIK没有命令来创build数据库或做任何forms的DDL工作。 这是“实体SQL”语言的devise限制

EDMXdevise表面将映射您当前的数据库模式,而不是其他方式

在EF中执行针对数据库的SQL命令

 using System.Data.EntityClient; ... EntityConnection conn = new EntityConnection(myContext.Connection.ConnectionString); conn.Open(); EntityCommand cmd = conn.CreateCommand(); 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(); 

命令文本在实体SQL中,与T-SQL不是100%相同的

从EF中的插入中获取新的标识值

 Create Table dbo.MyItem ( Id int indentity(1, 1) Primary Key, Value varchar(100) ) var newItem = new MyItem() { Value = "Hello" }; context.AddToMyItem(newItem); context.SaveChanges(true); var theNewIdentityValue = newItem.Id; 

EF伙计们只是简单的做了这件事,不错的工作:-)

在L2S中,你可以使用像函数调用这样的存储过程。 在EF中,SP必须返回一个实体。 如果您的SP仅返回完整实体的子集,则可能会导致问题