Подтвердить что ты не робот

Как перейти от Linq 2 SQL к Linq 2 Entities?

Я хотел бы начать ссылку для людей, которые хотят перейти от linq2sql к linq2entities и ADO.net Entity Framework (здесь называется L2E). Я не хочу обсуждать, какая из этих двух лучше. Я просто хочу создать список различий между этими двумя для людей, которые хотят перейти от одного к другому.

Базовый материал прост: удалите классы данных linq2sql, добавьте модель ado.net(созданную из базы данных). Переименуйте "Entities" в имя прежнего 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();
}    


Для других фрагментов кода я пропущу часть использования (...) и SubmitChanges/SaveChanges, так как она будет одинаковой каждый раз.
Привязать измененный объект к datacontext/model в L2S (используя временную метку):
mydc.MyTable.Attach(myRow);

В L2E:

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


К привязать измененный объект к datacontext/model в L2S (используя оригинальный объект):
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);


В показать созданные команды SQL для отладки в L2S:
mydc.Log = Console.Out;
// before mydc.SubmitChanges();

В L2E вы можете показать SQL для запроса (спасибо TFD):

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

К сожалению, я не нашел способа вывода SQL, сгенерированного для вызова SaveChanges(), - вам нужно будет использовать профайлер SQL для этого.


To Создать базу данных из схемы, если не существует L2S:
if (!mydc.DatabaseExists())
  mydc.CreateDatabase();

В L2E:

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


Чтобы выполнить команду SQL для базы данных в L2S:
mydc.ExecuteCommand("ALTER TABLE dbo.MyTable ADD CONSTRAINT DF_MyTable_ID DEFAULT (newid()) FOR MyTableID");

В L2E:

Чтобы выполнить команду eSQL для базы данных в EF (будьте осторожны, 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();
}

Текст команды находится в Entity SQL, который не на 100% совпадает с T-SQL.
(благодаря TFD)

Если вам нужны команды DDL/DML в одном и том же соединении, вам может понадобиться создать соединение с базой данных самостоятельно, подключить EF, используя ваше собственное соединение db, и использовать это соединение для своих команд 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-класса, переопределите частичный метод 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


Вставка записи в MyTable с соответствующим MySubTable в L2S:
  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. Если я использую пользовательские функции в 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, похоже, работает только с использованием идентификатора типа sql.

(Я соберу больше различий в этом посте, когда я наткнусь на них, или как кто-то добавит их в ответы)

Некоторые ссылки, возможно, полезны:
- Разница между Transact-SQL и Entity-SQL
- NET - ADO.NET Entity Framework и LINQ для объектов
- Майк Таути о отключенном LINQ to Entities (для бета 2 из L2E)

4b9b3361

Ответ 1

Чтобы показать созданные команды SQL для отладки в EF

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

AFAIK нет команд для создания БД или работы DDL. Это ограничение дизайна языка "Entity SQL"

Поверхность проектирования EDMX отобразит вашу текущую схему базы данных, а не наоборот.

Ответ 2

Чтобы выполнить команду SQL для базы данных в EF

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

Текст команды находится в Entity SQL, который не на 100% совпадает с T-SQL

Ответ 3

Чтобы получить новое значение идентификации из вставки в 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 просто сделали это легкой, приятной работой: -)

Ответ 4

В L2S вы можете просто использовать хранимые процедуры, такие как вызовы функций. В EF SP должен вернуть объект. Это может вызвать проблемы, если ваш SP возвращает только подмножество полного объекта