parse net convert .net linq-to-sql linq-to-entities

.net - net - linq parse int



¿Cómo pasar de Linq 2 SQL a Linq 2 Entities? (4)

Me gustaría comenzar una referencia para las personas que desean pasar de linq2sql a linq2entities y ADO.net Entity Framework (aquí llamado L2E). No quiero discutir cuál de estos dos es mejor. Solo quiero crear una lista de diferencias entre estos dos para las personas que desean hacer la transición de uno a otro.

Lo básico es fácil: elimine las clases de datos linq2sql, agregue el modelo ado.net (creado a partir de la base de datos). Cambie el nombre de ''Entidades'' al nombre del antiguo contexto de datos.

Ahora, las diferencias. Por ejemplo, para persistir (guardar) los cambios en L2S que usaría:

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

En L2E esto debería cambiarse a:

using (MyDataClassesDataContext mydc = new MyDataClassesDataContext()) { // change data mydc.SaveChanges(); } Segundo ejemplo, para insertar un nuevo registro en L2S que usarías :

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

En L2E esto debería cambiarse a:

using (MyDataClassesDataContext mydc = new MyDataClassesDataContext()) { MyTable myRow = new MyTable(); // or = MyTable.CreateMyTable(...); mydc.AddToMyTable(myRow); mydc.SaveChanges(); } Para los otros fragmentos de código, omitiré la parte using (...) y los SubmitChanges / SaveChanges, ya que siempre es el mismo.
Para adjuntar un objeto cambiado a un contexto de datos / modelo en L2S (usando la marca de tiempo):

mydc.MyTable.Attach(myRow);

En L2E:

// you can use either mydc.Attach(myRow); // or (have not tested this) mydc.AttachTo("MyTable", myRow); Para adjuntar un objeto cambiado a un contexto de datos / modelo en L2S (utilizando el objeto original) :

mydc.MyTable.Attach(myRow, myOriginalRow);

En L2E ( MSDN - Aplicar cambios realizados a un objeto separado ):

mydc.Attach(myOriginalRow); mydc.ApplyPropertyChanges(myOriginalRow.EntityKey.EntitySetName, myRow); Para eliminar un registro en L2S :

mydc.MyTable.DeleteOnSubmit(myRow);

En L2E:

mydc.DeleteObject(myRow); Para mostrar los comandos SQL creados para la depuración en L2S :

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

En L2E puede mostrar el SQL para una consulta (gracias a TFD):

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

Lamentablemente, no encontré la forma de generar el SQL generado para una llamada a SaveChanges (); necesitaría usar un generador de perfiles SQL para esto.

Para crear una base de datos desde el esquema si no existe L2S :

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

En L2E:

// according to TFD there are no DDL commands in L2E Para ejecutar un comando SQL contra la base de datos en L2S :

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

En L2E:

Para ejecutar un comando eSQL contra la base de datos en EF (cuidado, eSQL aún no soporta los comandos DDL o DML (alterar, Insertar, actualizar, eliminar)):

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

El texto de comando está en Entity SQL que no es 100% lo mismo que T-SQL.
(gracias a TFD)

Si necesita comandos DDL / DML en la misma conexión, puede que necesite crear la conexión de la base de datos usted mismo, conecte el EF utilizando su conexión db propia y use esta conexión para sus comandos DML. No es bonito, échale un vistazo:

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 } Para proporcionar valores predeterminados para una clase L2S recién creada, anule el método parcial OnCreated:

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

En L2E puedes simplemente crear un constructor predeterminado para tu clase de tabla:

partial class MyTable { public MyTable() { Name = ""; } } Los siguientes ejemplos son sobre una relación 1: n entre dos tablas. Defino la tabla aquí en SQL, para que sepa de lo que estoy escribiendo:

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 Insertar un registro en MyTable con la MySubTable correspondiente en L2S :

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

Muy similar en L2E:

MyTable myRow = new MyTable(); myRow.MySubTable.Add(new MySubTable()); mydc.AddToSaLyWebsites(test); En L2S para buscar en una subtabla , puede usar:

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

En L2E no puede acceder a las columnas de relación:

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

(por supuesto, también podrías usar)

from u in _searchForTable.MySubTable where u.Name == _searchForName select u

(Nota al margen: no es necesario que _searchForTable esté adjuntado al EF para que esto funcione).

Notas misceláneas:

En L2S puedo usar funciones misceláneas en LINQ. Si uso funciones personalizadas en L2E obtengo una NotSupportedException. Entonces, en lugar de

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

En L2E uno necesitaría usar

DateTime endDate = _searchForDate.AddHours(2); from t in mydc.MyTable where t.Date >= _searchForDate && t.Date <= endDate select t; Mientras que L2S puede leer valores autogenerados de la base de datos, como, por ejemplo, la ID autogenerada, en L2E esto parece funcionar solo usando la identidad de tipo sql.

(Recogeré más diferencias en esta publicación cuando me tropiece con ellas o cuando alguien las agregue en las respuestas)

Algunos enlaces, quizás útiles:
- Diferencia entre Transact-SQL y Entity-SQL
- NET - ADO.NET Entity Framework y LINQ a entidades
- Mike Taulty sobre LINQ desconectado a entidades (para beta 2 de L2E)


En L2S puedes usar procedimientos almacenados como llamadas a funciones. En EF, el SP debe devolver una entidad. Esto puede causar problemas si su SP solo devuelve un subconjunto de una entidad completa


Obtener el nuevo valor de identidad de un inserto en 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;

La gente de EF acaba de hacer que esto sea fácil, buen trabajo :-)


Para ejecutar un comando SQL contra la base de datos en 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();

El texto de comando está en Entity SQL que no es 100% lo mismo que T-SQL


Para mostrar los comandos SQL creados para la depuración en EF

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

AFAIK no hay comandos para crear DB o hacer ningún tipo de trabajo DDL. Esta es la limitación de diseño del lenguaje "Entity SQL"

La superficie de diseño de EDMX mapeará su esquema de base de datos actual, no al revés