entity-framework-4.1 - ejemplo - crear base de datos entity framework
¿Puede crear vistas de SQL/procedimientos almacenados utilizando Entity Framework 4.1 Código primer acercamiento (7)
¡El diseño de emp funciona como un campeón! Estoy usando su patrón pero también asigno procedimientos almacenados dentro de mi clase DbContext que permite simplemente llamar a esos métodos de contexto en lugar de usar SqlQuery () y llamar a los procedimientos directamente desde mi repositorio. Como las cosas pueden ponerse un poco complicadas cuando la aplicación crece, he creado una verificación dentro de mi método Seed que se asegura de que el recuento real de parámetros del procedimiento almacenado coincida con el recuento de parámetros en el método de mapeo. También he actualizado el bucle DROP emp mencionado. En lugar de tener que mantener una carpeta / archivo separado para las declaraciones de descarte, simplemente leo la primera línea de cada archivo sql y sustituyo CREATE
con DROP
(solo asegúrese de que la primera línea sea siempre simplemente CREATE PROCEDURE ProcName
). De esta manera, todos los procedimientos en mi carpeta StoredProcs se eliminan y se vuelven a crear cada vez que se ejecuta Update-Database. La caída también se envuelve en un bloque try-catch en caso de que el procedimiento sea nuevo. Para que el conteo de parámetros de procedimiento funcione, deberá asegurarse de envolver un bloque BEGIN/END
alrededor de su tsql, ya que cada línea del archivo se lee hasta BEGIN. También asegúrese de que cada parámetro sp esté en la nueva línea.
// Drop Stored Procs
foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..//DataContext//SiteMigrations//StoredProcs"), "*.sql"))
{
// Try to drop proc if its already created
// Without this, for new procs, seed method fail on trying to delete
try
{
StreamReader reader = new StreamReader(file);
// Read first line of file to create drop command (turning CREATE [dbo].[TheProc] into DROP [dbo].[TheProc])
string dropCommand = reader.ReadLine().Replace("CREATE", "DROP");
context.Database.ExecuteSqlCommand(dropCommand, new object[0]);
}
catch { }
}
// Add Stored Procs
foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..//DataContext//SiteMigrations//StoredProcs"), "*.sql"))
{
// File/Proc names must match method mapping names in DbContext
int lastSlash = file.LastIndexOf(''//');
string fileName = file.Substring(lastSlash + 1);
string procName = fileName.Substring(0, fileName.LastIndexOf(''.''));
// First make sure proc mapping in DbContext contain matching parameters. If not throw exception.
// Get parameters for matching mapping
MethodInfo mi = typeof(SiteContext).GetMethod(procName);
if (mi == null)
{
throw new Exception(String.Format("Stored proc mapping for {0} missing in DBContext", procName));
}
ParameterInfo[] methodParams = mi.GetParameters();
// Finished getting parameters
// Get parameters from stored proc
int spParamCount = 0;
using (StreamReader reader = new StreamReader(file))
{
string line;
while ((line = reader.ReadLine()) != null)
{
// If end of parameter section, break out
if (line.ToUpper() == "BEGIN")
{
break;
}
else
{
if (line.Contains("@"))
{
spParamCount++;
}
}
}
}
// Finished get parameters from stored proc
if (methodParams.Count() != spParamCount)
{
string err = String.Format("Stored proc mapping for {0} in DBContext exists but has {1} parameter(s)" +
" The stored procedure {0} has {2} parameter(s)", procName, methodParams.Count().ToString(), spParamCount.ToString());
throw new Exception(err);
}
else
{
context.Database.ExecuteSqlCommand(File.ReadAllText(file), new object[0]);
}
}
¡Disfrutar!
Entity Framework 4.1 Code First funciona muy bien al crear tablas y relaciones. ¿Es posible crear vistas SQL o procedimientos almacenados utilizando el enfoque de Code first? Cualquier puntero con respecto a esto será altamente apreciado. ¡Muchas gracias!
A primera vista, me gusta mucho el enfoque de Carl G, pero implica mucha interacción manual. En mi caso, siempre descarto todos los procedimientos almacenados, vistas ... y los vuelvo a crear siempre que haya un cambio en la base de datos. De esta manera estamos seguros de que todo está actualizado con la última versión.
La recreación ocurre al configurar el siguiente Inicializador:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>());
Entonces nuestro método de semilla será llamado cuando haya una migración lista
protected override void Seed(DeploymentLoggingContext context)
{
// Delete all stored procs, views
foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sql//Seed"), "*.sql"))
{
context.Database.ExecuteSqlCommand(File.ReadAllText(file), new object[0]);
}
// Add Stored Procedures
foreach (var file in Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Sql//StoredProcs"), "*.sql"))
{
context.Database.ExecuteSqlCommand(File.ReadAllText(file), new object[0]);
}
}
Las declaraciones SQL se almacenan en archivos * .sql para facilitar la edición. Asegúrese de que sus archivos tengan "Acción de compilación" configurada en "Contenido" y "Copiar en el directorio de salida" configurada en "Copiar siempre". Buscamos las carpetas y ejecutamos todos los scripts dentro. No olvide excluir las declaraciones "GO" en su SQL porque no pueden ejecutarse con ExecuteSqlCommand ().
Mi diseño de directorio actual es el siguiente:
Proyecto.DAL
+ Migraciones
+ Sql
++ Semilla
+++ dbo.cleanDb.sql
++ StoredProcs
+++ dbo.sp_GetSomething.sql
Ahora solo tiene que colocar procedimientos almacenados adicionales en la carpeta y todo se actualizará adecuadamente.
Admitimos procedimientos almacenados en nuestro Código de Entity Framework First Migrations. Nuestro enfoque es crear una carpeta para guardar los archivos .sql (~ / Sql / por ejemplo). Cree archivos .sql en la carpeta para crear y eliminar el procedimiento almacenado. Por ejemplo, Create_sp_DoSomething.sql
y Drop_sp_DoSomething
. Debido a que el SQL se ejecuta en un lote y CREATE PROCEDURE..
debe ser la primera declaración de un lote, haga que CREATE PROCEDURE...
la primera declaración en el archivo. Además, no pongas GO
después de la DROP...
Agregue un archivo de recursos a su proyecto, si aún no tiene uno. Arrastre los archivos .sql desde el explorador de soluciones a la vista Archivos del diseñador de Recursos. Ahora cree una migración vacía ( Add-Migration SomethingMeaningful_sp_DoSomething
) y use:
namespace MyApplication.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class SomethingMeaningful_sp_DoSomething : DbMigration
{
public override void Up()
{
this.Sql(Properties.Resources.Create_sp_DoSomething);
}
public override void Down()
{
this.Sql(Properties.Resources.Drop_sp_DoSomething);
}
}
}
~ / Sql / Create_sp_DoSomething.sql
CREATE PROCEDURE [dbo].[sp_DoSomething] AS
BEGIN TRANSACTION
-- Your stored procedure here
COMMIT TRANSACTION
GO
~ / Sql / Drop_sp_DoSomething.sql
DROP PROCEDURE [dbo].[sp_DoSomething]
Como señaló Ladislav, DbContext
en general tiende a minimizar la lógica en la base de datos, pero es posible ejecutar SQL personalizado usando context.Database.ExecuteSqlCommand()
o context.Database.SqlQuery()
.
El enfoque de código primero de EF espera que no haya lógica en la base de datos. Eso significa que no hay procedimientos almacenados y no hay vistas de base de datos. Debido a que el enfoque de código primero no proporciona ningún mecanismo para generar tales construcciones automáticamente para usted. ¿Cómo podría hacer eso si significa generar lógica?
Deben crearlos en el inicializador de base de datos personalizado mediante la ejecución manual de los scripts de creación. No creo que estas construcciones SQL personalizadas puedan ser manejadas por migraciones SQL.
Para ampliar la respuesta de bbodenmiller , en Entity Framework 6, la clase DbMigration tiene métodos como AlterStoredProcedure que permiten la modificación de procedimientos almacenados sin tener que descender completamente a SQL en bruto.
Este es un ejemplo de un método de migración Up()
que altera un procedimiento almacenado de SQL Server existente llamado EditItem que toma tres parámetros de tipo int
, nvarchar(50)
y smallmoney
, respectivamente:
public partial class MyCustomMigration : DbMigration
{
public override void Up()
{
this.AlterStoredProcedure("dbo.EditItem", c => new
{
ItemID = c.Int(),
ItemName = c.String(maxLength:50),
ItemCost = c.Decimal(precision: 10, scale: 4, storeType: "smallmoney")
}, @" (Stored procedure body SQL goes here) "
}
//...
}
En mi máquina, este script de migración produce el siguiente SQL:
ALTER PROCEDURE [dbo].[EditItem]
@ItemID [int],
@ItemName [nvarchar](50),
@ItemCost [smallmoney]
AS
BEGIN
(Stored procedure body SQL goes here)
END
Parece estar mal documentado, sin embargo, parece que ahora puede hacer algo de manipulación de procedimientos almacenados utilizando AlterStoredProcedure , CreateStoredProcedure , DropStoredProcedure , MoveStoredProcedure , RenameStoredProcedure en Entity Framework 6. No los he probado todavía, no puedo dar un ejemplo de cómo hacerlo. usalos, usalos a ellos.