私はEntity Framework 6を初めて使うので、自分のプロジェクトにストアドプロシージャを実装したいと思います。次のようなストアドプロシージャがあります。
ALTER PROCEDURE [dbo].[insert_department]
@Name [varchar](100)
AS
BEGIN
INSERT [dbo].[Departments]([Name])
VALUES (@Name)
DECLARE @DeptId int
SELECT @DeptId = [DeptId]
FROM [dbo].[Departments]
WHERE @@ROWCOUNT > 0 AND [DeptId] = SCOPE_IDENTITY()
SELECT t0.[DeptId]
FROM [dbo].[Departments] AS t0
WHERE @@ROWCOUNT > 0 AND t0.[DeptId] = @DeptId
END
Department
クラス:
public class Department
{
public int DepartmentId { get; set; }
public string Name { get; set; }
}
modelBuilder
.Entity<Department>()
.MapToStoredProcedures(s =>
s.Update(u => u.HasName("modify_department")
.Parameter(b => b.Department, "department_id")
.Parameter(b => b.Name, "department_name"))
.Delete(d => d.HasName("delete_department")
.Parameter(b => b.DepartmentId, "department_id"))
.Insert(i => i.HasName("insert_department")
.Parameter(b => b.Name, "department_name")));
protected void btnSave_Click(object sender, EventArgs e)
{
string department = txtDepartment.text.trim();
// here I want to call the stored procedure to insert values
}
私の問題は次のとおりです。 /ストアドプロシージャを呼び出してパラメータを渡す方法を教えてください。
以下のようにDbContext
クラスのストアドプロシージャを呼び出すことができます。
this.Database.SqlQuery<YourEntityType>("storedProcedureName",params);
ただし、ストアドプロシージャがサンプルコードとして複数の結果セットを返す場合は、MSDNでこの役に立つ記事を見ることができます。
ストアドプロシージャから返される結果と同じプロパティ名を持つオブジェクトを作成するだけです。次のストアドプロシージャの場合
CREATE PROCEDURE [dbo].[GetResultsForCampaign]
@ClientId int
AS
BEGIN
SET NOCOUNT ON;
SELECT AgeGroup, Gender, Payout
FROM IntegrationResult
WHERE ClientId = @ClientId
END
次のようなクラスを作成してください。
public class ResultForCampaign
{
public string AgeGroup { get; set; }
public string Gender { get; set; }
public decimal Payout { get; set; }
}
そして、次のようにしてプロシージャを呼び出します。
using(var context = new DatabaseContext())
{
var clientIdParameter = new SqlParameter("@ClientId", 4);
var result = context.Database
.SqlQuery<ResultForCampaign>("GetResultsForCampaign @ClientId", clientIdParameter)
.ToList();
}
結果はResultForCampaign
オブジェクトのリストを含みます。 SqlQuery
は必要に応じていくつでもパラメータを使って呼び出すことができます。
ExecuteSqlCommand
で解決しました
私のようなあなた自身のメソッドをあなた自身のインスタンスとしてDbContextに入れてください:
public void addmessage(<yourEntity> _msg)
{
var date = new SqlParameter("@date", _msg.MDate);
var subject = new SqlParameter("@subject", _msg.MSubject);
var body = new SqlParameter("@body", _msg.MBody);
var fid = new SqlParameter("@fid", _msg.FID);
this.Database.ExecuteSqlCommand("exec messageinsert @Date , @Subject , @Body , @Fid", date,subject,body,fid);
}
だからあなたはこのようなあなたのコードビハインドでメソッドを持つことができます:
[WebMethod] //this method is static and i use web method because i call this method from client side
public static void AddMessage(string Date, string Subject, string Body, string Follower, string Department)
{
try
{
using (DBContext reposit = new DBContext())
{
msge <yourEntity> Newmsg = new msge();
Newmsg.MDate = Date;
Newmsg.MSubject = Subject.Trim();
Newmsg.MBody = Body.Trim();
Newmsg.FID= 5;
reposit.addmessage(Newmsg);
}
}
catch (Exception)
{
throw;
}
}
これは私のSPです。
Create PROCEDURE dbo.MessageInsert
@Date nchar["size"],
@Subject nchar["size"],
@Body nchar["size"],
@Fid int
AS
insert into Msg (MDate,MSubject,MBody,FID) values (@Date,@Subject,@Body,@Fid)
RETURN
あなたを助けてくれることを願っています
あなたの例を使用して、これを達成するための2つの方法があります。
このコードは、マッピングの有無にかかわらず機能します。エンティティのマッピングを無効にすると、EFはinsert + select文を生成します。
protected void btnSave_Click(object sender, EventArgs e)
{
using (var db = DepartmentContext() )
{
var department = new Department();
department.Name = txtDepartment.text.trim();
db.Departments.add(department);
db.SaveChanges();
// EF will populate department.DepartmentId
int departmentID = department.DepartmentId;
}
}
protected void btnSave_Click(object sender, EventArgs e)
{
using (var db = DepartmentContext() )
{
var name = new SqlParameter("@name, txtDepartment.text.trim());
//to get this to work, you will need to change your select inside dbo.insert_department to include name in the resultset
var department = db.Database.SqlQuery<Department>("dbo.insert_department @name", name).SingleOrDefault();
//alternately, you can invoke SqlQuery on the DbSet itself:
//var department = db.Departments.SqlQuery("dbo.insert_department @name", name).SingleOrDefault();
int departmentID = department.DepartmentId;
}
}
部署オブジェクトを直接操作してSqlParameterオブジェクトの束を作成する必要がないため、最初の方法を使用することをお勧めします。
エンティティをストアドプロシージャにマッピングしていることを示すMapToStoredProcedures()
を使用しています。これを行うときは、ストアドプロシージャがあることを放棄し、通常どおりにcontext
を使用する必要があります。このようなもの( ブラウザに書かれているのでテストされていない )
using(MyContext context = new MyContext())
{
Department department = new Department()
{
Name = txtDepartment.text.trim()
};
context.Set<Department>().Add(department);
}
あなたが本当にしようとしているのが直接ストアドプロシージャを呼び出すことであるならば、それから SqlQuery
を使ってください
また、ストアード・プロシージャー(複数の結果セットを返すストアード・プロシージャーを含む)、TVF、およびスカラーUDFをEFからネイティブに呼び出すことを可能にする、私が作成した規則を使用することもできます。
Entity Framework 6.1がリリースされるまでは、ストア関数(つまりテーブル値関数とストアドプロシージャ)は、データベース優先を実行する場合にのみEFで使用できました。 Code Firstアプリでストア関数を呼び出すことを可能にするいくつかの回避策がありましたが、それでも最大の制限の1つであるLinqクエリでTVFを使用できませんでした。 EF 6.1では、マッピングAPIが公開され、(追加の調整と共に)Code Firstアプリでストア関数を使用できるようになりました。
私は過去2週間非常に懸命に取り組んできましたが、それがここにあります - コードファーストアプローチとEntity Framework 6.1.1を使用するアプリケーションでストア関数(ストアドプロシージャ、テーブル値関数など)を使用できるようにする規約のベータ版または新しい)。このリリースに含まれる修正と新機能に満足しています。
続きを読む 。
これは、パラメータを渡している間にストアドプロシージャからデータを引き戻すことによって私には有効です。
var param = new SqlParameter("@datetime", combinedTime);
var result =
_db.Database.SqlQuery<QAList>("dbo.GetQAListByDateTime @datetime", param).ToList();
_db
はdbContextです
挿入、更新、および削除を行うためのストアドプロシージャとEF 6のマッピングの仕組みを示すこのリンクを見てください。 http://msdn.Microsoft.com/en-us/data/dn468673
加算
これは、Code Firstからストアドプロシージャを呼び出す優れた例です。
単一のパラメータを使用してストアドプロシージャを実行する必要があり、そのストアドプロシージャはエンティティの状態と一致するデータのセットを返すとします。
var countryIso = "AR"; //Argentina
var statesFromArgentina = context.Countries.SqlQuery(
"dbo.GetStatesFromCountry @p0", countryIso
);
2つのパラメータを使って別のストアドプロシージャを実行したいとしましょう。
var countryIso = "AR"; //Argentina
var stateIso = "RN"; //Río Negro
var citiesFromRioNegro = context.States.SqlQuery(
"dbo.GetCitiesFromState @p0, @p1", countryIso, stateIso
);
パラメータにインデックスベースの命名を使用していることに注意してください。これは、SQLインジェクションの問題を回避するために、Entity FrameworkがこれらのパラメーターをDbParameterオブジェクトとしてラップするためです。
この例が役立つことを願っています!
object[] xparams = {
new SqlParameter("@ParametterWithNummvalue", DBNull.Value),
new SqlParameter("@In_Parameter", "Value"),
new SqlParameter("@Out_Parameter", SqlDbType.Int) {Direction = ParameterDirection.Output}};
YourDbContext.Database.ExecuteSqlCommand("exec StoreProcedure_Name @ParametterWithNummvalue, @In_Parameter, @Out_Parameter", xparams);
var ReturnValue = ((SqlParameter)params[2]).Value;
public IList<Models.StandardRecipeDetail> GetRequisitionDetailBySearchCriteria(Guid subGroupItemId, Guid groupItemId)
{
var query = this.UnitOfWork.Context.Database.SqlQuery<Models.StandardRecipeDetail>("SP_GetRequisitionDetailBySearchCriteria @SubGroupItemId,@GroupItemId",
new System.Data.SqlClient.SqlParameter("@SubGroupItemId", subGroupItemId),
new System.Data.SqlClient.SqlParameter("@GroupItemId", groupItemId));
return query.ToList();
}
最初はコードで動作します。ビューモデル(StudentChapterCompletionViewModel)のプロパティが一致するリストを返します
var studentIdParameter = new SqlParameter
{
ParameterName = "studentId",
Direction = ParameterDirection.Input,
SqlDbType = SqlDbType.BigInt,
Value = studentId
};
var results = Context.Database.SqlQuery<StudentChapterCompletionViewModel>(
"exec dbo.sp_StudentComplettion @studentId",
studentIdParameter
).ToList();
コンテキスト用に更新
Contextは、DbContextを継承したクラスのインスタンスです。
public class ApplicationDbContext : DbContext
{
public DbSet<City> City { get; set; }
}
var Context = new ApplicationDbContext();
マインドレスパッセンジャー エンティティフレームワークを使用してストアドプロシージャから複数の結果セットを返すことができるプロジェクトがあります。下記の彼の例の1つ....
using (testentities te = new testentities())
{
//-------------------------------------------------------------
// Simple stored proc
//-------------------------------------------------------------
var parms1 = new testone() { inparm = "abcd" };
var results1 = te.CallStoredProc<testone>(te.testoneproc, parms1);
var r1 = results1.ToList<TestOneResultSet>();
}
テーブルパラメータをストアドプロシージャに渡したい場合は、テーブルパラメータにTypeNameプロパティを設定する必要があります。
SqlParameter codesParam = new SqlParameter(CODES_PARAM, SqlDbType.Structured);
SqlParameter factoriesParam = new SqlParameter(FACTORIES_PARAM, SqlDbType.Structured);
codesParam.Value = tbCodes;
codesParam.TypeName = "[dbo].[MES_CodesType]";
factoriesParam.Value = tbfactories;
factoriesParam.TypeName = "[dbo].[MES_FactoriesType]";
var list = _context.Database.SqlQuery<MESGoodsRemain>($"{SP_NAME} {CODES_PARAM}, {FACTORIES_PARAM}"
, new SqlParameter[] {
codesParam,
factoriesParam
}
).ToList();
コードファーストアプローチでストアドプロシージャを呼び出すのは便利ではないことがわかりました。代わりにDapper
を使うのが好きです。
次のコードはEntity Framework
で書かれています。
var clientIdParameter = new SqlParameter("@ClientId", 4);
var result = context.Database
.SqlQuery<ResultForCampaign>("GetResultsForCampaign @ClientId", clientIdParameter)
.ToList();
次のコードはDapper
で書かれています。
return Database.Connection.Query<ResultForCampaign>(
"GetResultsForCampaign ",
new
{
ClientId = 4
},
commandType: CommandType.StoredProcedure);
2番目のコードは理解しやすいと思います。
なにもする必要はありません。コードの最初のアプローチとしてdbcontextを作成する場合は、流れるようなAPI領域の下の名前空間を初期化し、spのリストを作成し、それを必要な場所に使用します。
public partial class JobScheduleSmsEntities : DbContext
{
public JobScheduleSmsEntities()
: base("name=JobScheduleSmsEntities")
{
Database.SetInitializer<JobScheduleSmsEntities>(new CreateDatabaseIfNotExists<JobScheduleSmsEntities>());
}
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<ReachargeDetail> ReachargeDetails { get; set; }
public virtual DbSet<RoleMaster> RoleMasters { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//modelBuilder.Types().Configure(t => t.MapToStoredProcedures());
//modelBuilder.Entity<RoleMaster>()
// .HasMany(e => e.Customers)
// .WithRequired(e => e.RoleMaster)
// .HasForeignKey(e => e.RoleID)
// .WillCascadeOnDelete(false);
}
public virtual List<Sp_CustomerDetails02> Sp_CustomerDetails()
{
//return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Sp_CustomerDetails02>("Sp_CustomerDetails");
// this.Database.SqlQuery<Sp_CustomerDetails02>("Sp_CustomerDetails");
using (JobScheduleSmsEntities db = new JobScheduleSmsEntities())
{
return db.Database.SqlQuery<Sp_CustomerDetails02>("Sp_CustomerDetails").ToList();
}
}
}
}
public partial class Sp_CustomerDetails02
{
public long? ID { get; set; }
public string Name { get; set; }
public string CustomerID { get; set; }
public long? CustID { get; set; }
public long? Customer_ID { get; set; }
public decimal? Amount { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public int? CountDay { get; set; }
public int? EndDateCountDay { get; set; }
public DateTime? RenewDate { get; set; }
public bool? IsSMS { get; set; }
public bool? IsActive { get; set; }
public string Contact { get; set; }
}
MySqlとEntity Frameworkのコードを最初に使用する
public class Vw_EMIcount
{
public int EmiCount { get; set; }
public string Satus { get; set; }
}
var result = context.Database.SqlQuery<Vw_EMIcount>("call EMIStatus('2018-3-01' ,'2019-05-30')").ToList();
public static string ToSqlParamsString(this IDictionary<string, string> dict)
{
string result = string.Empty;
foreach (var kvp in dict)
{
result += $"@{kvp.Key}='{kvp.Value}',";
}
return result.Trim(',', ' ');
}
public static List<T> RunSproc<T>(string sprocName, IDictionary<string, string> parameters)
{
string command = $"exec {sprocName} {parameters.ToSqlParamsString()}";
return Context.Database.SqlQuery<T>(command).ToList();
}
これはEF(DBファースト)がDbContextクラスで生成するものです。
public ObjectResult<int> Insert_Department(string department)
{
var departmentParameter = new ObjectParameter("department", department);
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<int>("insert_department", departmentParameter);
}
あなたがテーブル選択オプションでストアドプロシージャを選択した場合、EDMXが今回作成するときは、単にプロシージャ名を使用してストアドプロシージャを呼び出す...
var num1 = 1;
var num2 = 2;
var result = context.proc_name(num1,num2).tolist();// list or single you get here.. using same thing you can call insert,update or delete procedured.