2009-02-26 9 views
42

Me gustaría comenzar una referencia para las personas que quieren 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.¿Cómo pasar de Linq 2 SQL a Linq 2 Entities?

Lo básico es fácil: elimine las clases de datos linq2sql, agregue el modelo de 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, a persistir (guardar) los cambios en L2S que haría uso:

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

En L2E esto tendría que ser cambiado a:

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


segundo ejemplo, para insertar una nuevo récord en L2S se usaría:

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

en L2E esto tendría que ser cambiado 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 Voy a saltar el (...) parte el uso y las SubmitChanges/SaveChanges, ya que es el mismo cada vez.
Para adjuntar un objeto modificado a un DataContext/modelo en L2S (usando timestamp):

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 DataContext/modelo en L2S (utilizando el objeto original):

mydc.MyTable.Attach(myRow, myOriginalRow); 

En L2E (MSDN - Apply Changes Made to a Detached Object):

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 muestran los comandos SQL creada para depuración en L2S:

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

En L2E you can show the SQL for a query (gracias a TFD):

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

Lamentablemente, no he encontrado ninguna manera de salida el SQL generado por una llamada a SaveChanges() - que había necesidad de utilizar para este a SQL profiler .


Para Crear una base de datos del esquema si no existe ninguno L2S:

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

En L2E:

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


Para ejecutar un comando SQL en 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 la FE (cuidado, eSQL no soporta DDL o DML (Alter, insertar, actualizar, eliminar) los comandos aún):

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, es posible que necesite para crear la conexión de base de datos usted mismo, conectar el EF usando su conexión db hecho a sí mismo, y utilizar esta conexión para sus comandos DML . No es bonita, echar un vistazo por ti mismo:

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 
} 


Proporcionar default values for a newly created L2S-Class reemplazar el método parcial OnCreated:

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

En L2E que sólo puede crear un constructor por defecto para la clase de tabla:

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


Los siguientes ejemplos son sobre una relación 1: n entre dos tablas. Yo defino la mesa aquí en SQL, para que sepa 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 


Inserción un registro en MiTabla con 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, se puede utilizar:

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

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

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

(por supuesto, también se puede utilizar)

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

(nota al margen extraña : _searchForTable no necesita estar adjunto al EF para que esto funcione.)


notas Miscellanous:

En L2S puedo usar las funciones VARIAS, en LINQ. Si uso funciones personalizadas en L2E obtengo una NotSupportedException. Así, en lugar de

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

En L2E uno tendría que usar

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


Mientras L2S puede leer los valores generados automáticamente desde la base de datos, como, por ejemplo, el ID autogenerado, en L2E esto parece solamente trabajo usando identidad de tipo sql.

(Voy a recoger más diferencias en este post como me tropiezo con ellos, o como alguien les añade en respuestas)

Algunos enlaces, tal vez útil:
- Difference between Transact-SQL and Entity-SQL
- NET - ADO.NET Entity Framework & LINQ to Entities
- Mike Taulty about Disconnected LINQ to Entities (for beta 2 of L2E)

+0

¿Quiere decir de Linq a Sql -> Entity Framework? – RobS

+0

marco de la entidad? Pensé que se llama linq a las entidades: http://msdn.microsoft.com/en-us/library/bb386964.aspx – Sam

+0

Entity Framework se encuentra en la parte superior de Linq a Entidades – RobS

Respuesta

6

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. Se trata de limitación de diseño del lenguaje "Entity SQL"

La superficie de diseño EDMX trazará un mapa del esquema de base de datos actual, no al revés

3

Para ejecutar un comando SQL en 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% igual que T-SQL

+0

Me encantaría usar la misma conexión que utiliza el contexto. Intenté EntityConnection conn = new EntityConnection (myContext.MetadataWorkspace, myContext.Conexión), pero esto funciona como una funky InvalidoperationException (algo así como System.Data.SqlClient no es lo mismo que el de connectionstring) – Sam

+0

Dang, para mi sorpresa, acabo de notar, EntitySQL (eSQL) no admite insertar, actualizar, eliminar comandos y la actualización masiva fue la razón principal para necesitarlo. Lástima. – Sam

1

Para 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 EF acaba de hacer esto para un trabajo fácil, agradable :-)

+0

¿Esto necesita identidad (1,1) para funcionar? No funciona con Guid, me parece? – Sam

1

En L2S sólo puede utilizar 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

Cuestiones relacionadas