当前位置:  开发笔记 > 数据库 > 正文

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

如何解决《如何从Linq2SQL迁移到Linq2实体?》经验,为你挑选了1个好方法。

我想为那些想要从linq2sql迁移到linq2entities和ADO.net Entity Framework(在这里称为L2E)的人们开始参考.我不想讨论哪两个更好.我只是想为那些想要从一个过渡到另一个的人创建这两者之间的差异列表.

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


现在,差异.例如,要在L2S中保留(保存)更改,我会使用:

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

在L2E中,这必须改为:

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中,这必须改为:

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


对于其他代码片段,我将跳过using(...)部分和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记录:

mydc.MyTable.DeleteOnSubmit(myRow);

在L2E中:

mydc.DeleteObject(myRow);


在L2S中显示用于调试的已创建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事件探查器.


创建一个从计划数据库中,如果不存在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(alter,Insert,update,delete)命令):

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)

如果在同一连接上需要DDL/DML命令,则可能需要自己创建数据库连接,使用自制数据库连接连接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
}


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

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

在L2E中,您只需为表类创建一个默认构造函数:

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记录插入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 中搜索子表,您可以使用:

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,但这似乎只能使用sql类型标识.

(我会在这篇文章中收集更多差异,因为我偶然发现它们,或者有人将它们添加到答案中)

一些链接,可能有用:
- Transact-SQL和Entity-SQL之间的区别
- NET - ADO.NET实体框架和LINQ到实体
- Mike Taulty关于断开连接LINQ到实体(针对L2E的beta 2)



1> TFD..:

显示已创建的用于在EF中进行调试的SQL命令

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

AFAIK没有命令来创建数据库或执行任何类型的DDL工作.这是"实体SQL"语言的设计限制

EDMX设计图面将映射您当前的数据库架构,而不是相反

推荐阅读
ar_wen2402851455
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有