如何从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中使用相应的MySubTable将logging插入到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仅返回完整实体的子集,则可能会导致问题