在当前版本之前,我已经有一段时间没有为我的实体类创建特殊的存储过程了。然后它被放在小桌子上。我创建了我的delete,非常好,但是我忘记了EF也会让你创建插入和更新。有没有人知道一种快速的方法?我有大约7-8个表,每个表大约有30-50列,我需要这样做,而不是期待打字。
发布于 2013-05-16 05:35:21
在SSMS工具中,CRUD存储过程的创建非常棒(也是众多特性之一)。http://www.ssmstoolspack.com/
发布于 2013-05-16 05:43:21
,然后是在较小的桌子上。我创建了我的delete,非常好,但是我忘记了EF让您创建插入和更新的以及
您在EntityFramework 5.0中添加了这个问题,所以我不太理解为什么需要为delete生成存储过程。
所有的CRUD (创建、读取、删除、更新)都是在DbContext上完成的,不需要为此编写过程。如果你有一个组织良好的数据库(有PKs,FKs和良好的索引),你就不需要有存储过程,因为你甚至可以编译EF的视图,这样你就可以得到更好的结果。
请参阅示例代码:
DbContext context = new YourContext();
public bool Delete<TEntity>(TEntity entity) where TEntity : class
{
var set = context.Set<TEntity>();
set.Attach(entity);
return true;
}
public bool Add<TEntity>(TEntity entity) where TEntity : class
{
var set = context.Set<TEntity>();
set.Add(entity);
return true;
}
您甚至不需要使用这种方法,您可以直接使用DbContext.Set,如下例所示:
void Run()
{
using (DbContext context = new MyContext())
{
//Create a new person to insert
var newItem = new Person() { Name = "Mike"} ;
var set = context.Set<Person>();
set.Add(newItem);
// Returns a record from database with PK = "John"
var itemToDelete = set.Find("John");
set.Remove(itemToDelete);
// This will add the new record, and delete "John" from the Database
context.SaveChanges();
}
}
所以您可以看到,CRUD不需要存储过程!
将存储过程用于其他内容,与数据库相关,不需要使用EF :)
有人知道一个快速的方法吗?我有大约7-8个表,每个表中有大约30-50列,我需要这样做,而不是期待输入。
这里要说明的是,在使用EF时,您不需要编写存储过程来处理CRUD操作。
你问我一种快速的方法(甚至提到你不想输入它们),我的回答是:
更快的方法是不做任何程序!这很快,而且可以避免键入! :)
演示的代码已经处理了您的需求,而不需要任何存储过程。:)
添加了信息
如果您认为需要删除存储过程的原因是您想要删除相关实体,并且您认为EF不处理此站点,则这是另一个问题,我可以告诉您一些可能的原因:
1)可能因为FK引用而以错误结束,这种情况下,请看一下here
2)错误可能是因为当您从与其他实体的关系中移除一个实体时,EF不会理解您想要逻辑删除该记录,您需要额外地将.ChangeState更改为Deleted。
请看下面这个例子:
public static void StudentLeaves(string name)
{
using (var context = new SchoolContext())
{
context.Students.Remove(context.Students.Single(s => s.Name == name));
context.SaveChanges();
}
}
上面的例子会删除这个学生,对吗?但是现在看看第二个例子
public static void StudantLeaveParticularSchool(string schoolName, string name)
{
using (var context = new SchoolContext())
{
var school = context.Schools.Single(a => a.Nome == schoolName);
school .Students.Remove(context.Students.Single(a => a.Nome == name));
context.SaveChanges();
}
}
下面的代码不会从数据库中删除学生,它只会删除关系!
如果您使用的是CodeFirst,您可以明确表示您想要使用DeleteCascade,如下所示:
modelBuilder
.Entity()
.HasRequired(s => s.Schools)
.WithMany(r => r.Students)
.WillCascadeOnDelete();
更新:
对于那些对创建存储过程有“魔力”方式感兴趣的人,我将告诉你一种方法,但我再次告诉你:如果你正在使用EF和最佳实践,没有必要这样做,当我第一次开始使用EF进行开发时,我也认为我需要这样做,所以我们编写了几个T4文件,在转眼间就生成了数百个存储过程。但经过一段时间后,我们发现这不是使用EF的正确方法,所以我们放弃了过程,并将T4从项目中删除,事情变得容易得多。
要创建这些过程,您需要编写T4文件。如果你想了解更多关于T4的信息,可以在这里找到(http://msdn.microsoft.com/en-us/library/vstudio/bb126247.aspx)
我将向您展示我们编写的DELETE creation T4模板(您还需要一些其他的基本.tt文件才能运行,因此请记住,这只是一个示例):
<#@ template language="C#" debug="true" #>
<#@ output extension=".sql" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.XML" #>
<#@ assembly name="Microsoft.SqlServer.ConnectionInfo" #>
<#@ assembly name="Microsoft.SqlServer.Smo" #>
<#@ assembly name="Microsoft.SqlServer.Management.Sdk.Sfc" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="Microsoft.SqlServer.Management.Smo" #>
<#@ import namespace="Microsoft.SqlServer.Management.Common" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
-- Winsys Solutions
-- Stored Procedure de delete para a tabela <#= this.SchemaName #>.<#= this.TableName #>
CREATE PROCEDURE <#= this.SchemaName #>.<#= this.TableName.Replace("TBWS4_", "PRWS4_") #>_Delete
<# WriteParameterDeclarations(this.Table); #>
AS
BEGIN
DELETE FROM
<#= this.SchemaName #>.<#= this.TableName #>
WHERE
<# WriteWhereClause(this.Table); #>
END
GO
<#@ include file="CommonSqlHelper.tt" #>
<#+
/// <summary>
/// Writes stored procedure parameter declarations for all columns in the
/// primary key and all TIMESTAMP columns of the specified table.
/// </summary>
void WriteParameterDeclarations(Table table)
{
PushIndent(" ");
int parameterIndex = 0;
foreach(Column column in table.Columns)
{
if (column.InPrimaryKey || column.DataType.SqlDataType == SqlDataType.Timestamp)
{
if (parameterIndex > 0)
WriteLine(",");
Write("@{0} {1}", column.Name, GetDataTypeDeclaration(column.DataType));
parameterIndex++;
}
}
PopIndent();
}
#>
<#+
string TableName
{
get { return (string) CallContext.GetData("DeleteStoredProcedure.TableName"); }
}
string SchemaName
{
get { return (string) CallContext.GetData("DeleteStoredProcedure.SchemaName"); }
}
Table Table
{
get { return (Table) CallContext.GetData("DeleteStoredProcedure.Table"); }
}
#>
辅助方法包括:
/// <summary>
/// Returns a string that contains T-SQL declaration for the specified data
/// type. For string data types this includes maximum length, for numeric
/// data types this includes scale and precision.
/// </summary>
string GetDataTypeDeclaration(DataType dataType)
{
string result = dataType.Name;
switch(dataType.SqlDataType)
{
case SqlDataType.Binary:
case SqlDataType.Char:
case SqlDataType.NChar:
case SqlDataType.NVarChar:
case SqlDataType.VarBinary:
case SqlDataType.VarChar:
result += string.Format("({0})", dataType.MaximumLength);
break;
case SqlDataType.NVarCharMax:
case SqlDataType.VarBinaryMax:
case SqlDataType.VarCharMax:
result += "(max)";
break;
case SqlDataType.Decimal:
case SqlDataType.Numeric:
result += string.Format("({0}, {1})", dataType.NumericPrecision, dataType.NumericScale);
break;
}
return result;
}
/// <summary>
/// Generates where clause for UPDATE and DELETE statements for the specified
/// table.
/// </summary>
void WriteWhereClause(Table table, bool includeAllColumns = false)
{
PushIndent(" ");
int whereIndex = 0;
foreach(Column column in table.Columns)
{
if (column.InPrimaryKey || column.DataType.SqlDataType == SqlDataType.Timestamp || includeAllColumns)
{
if (whereIndex > 0)
WriteLine(" AND");
if (includeAllColumns)
Write("({0} = @{0} OR @{0} IS NULL)", column.Name);
else
Write("{0} = @{0}", column.Name);
whereIndex++;
}
}
PopIndent();
}
https://stackoverflow.com/questions/16574566
复制相似问题