Я очень новичок в 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
}
Моя проблема: как я могу вызвать хранимую процедуру и передать в нее параметры?
Ответ 1
Вы можете вызвать хранимую процедуру в классе DbContext
следующим образом.
this.Database.SqlQuery<YourEntityType>("storedProcedureName",params);
Но если ваша хранимая процедура возвращает несколько наборов результатов в качестве кода примера, вы можете увидеть эту полезную статью в MSDN
Сохраненные процедуры с несколькими наборами результатов
Ответ 2
Все, что вам нужно сделать, это создать объект, который имеет те же имена свойств, что и результаты, возвращаемые хранимой процедурой. Для следующей хранимой процедуры:
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
, используя столько параметров, сколько необходимо.
Ответ 3
Я решил это с 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;
}
}
это мой ИП:
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
надежда помогла тебе
Ответ 4
Используя ваш пример, вот два способа сделать это:
1 - Использовать отображение хранимых процедур
Обратите внимание, что этот код будет работать с отображением или без него. Если вы отключите отображение объекта, EF сгенерирует оператор вставки + выбора.
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;
}
}
2 - Вызовите хранимую процедуру напрямую
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.
Ответ 5
Вы используете MapToStoredProcedures()
которая указывает, что вы отображаете свои сущности на хранимые процедуры, при этом вам нужно отпустить тот факт, что есть хранимая процедура, и использовать context
как обычно. Как то так (записано в браузере, поэтому не проверено)
using(MyContext context = new MyContext())
{
Department department = new Department()
{
Name = txtDepartment.text.trim()
};
context.Set<Department>().Add(department);
}
Если все, что вы действительно пытаетесь сделать, это вызвать хранимую процедуру напрямую, используйте SqlQuery
Ответ 6
Теперь вы можете использовать соглашение, которое я создал, которое позволяет вызывать хранимые процедуры (включая хранимые процедуры, возвращающие несколько наборов результатов), TVF и скалярные UDF изначально из EF.
До тех пор, пока не была выпущена функция Entity Framework 6.1, функции хранилища (т.е. табличные функции и хранимые процедуры) могут использоваться в EF только при выполнении Database First. Были некоторые обходные пути, которые позволили вызвать функции магазина в приложениях Code First, но вы все еще не могли использовать TVF в запросах Linq, что было одним из самых больших ограничений. В EF 6.1 API-интерфейс отображения был опубликован, что (наряду с некоторыми дополнительными настройками) позволило использовать функции хранилища в ваших приложениях Code First.
Подробнее
В течение последних двух недель я сильно затруднялся, и вот это - бета-версия соглашения, которая позволяет использовать функции хранилища (то есть хранимые процедуры, функции, связанные с таблицей и т.д.) в приложениях, которые используют подход Code First и Entity Framework 6.1.1 (или новее). Я более чем доволен исправлениями и новыми функциями, которые включены в этот выпуск.
Подробнее.
Ответ 7
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;
Ответ 8
Это работает для меня, отбрасывая данные из хранимой процедуры при передаче в параметре.
var param = new SqlParameter("@datetime", combinedTime);
var result =
_db.Database.SqlQuery<QAList>("dbo.GetQAListByDateTime @datetime", param).ToList();
_db
- это dbContext
Ответ 9
Взгляните на эту ссылку, которая показывает, как работает сопоставление EF 6 со хранимыми процедурами для вставки, обновления и удаления: http://msdn.microsoft.com/en-us/data/dn468673
Добавление
Вот отличный пример для вызова хранимой процедуры из Code First:
Предположим, что вам нужно выполнить хранимую процедуру с единственным параметром, и эта Хранимая процедура возвращает набор данных, которые соответствуют состояниям Entity, поэтому у нас будет следующее:
var countryIso = "AR"; //Argentina
var statesFromArgentina = context.Countries.SqlQuery(
"dbo.GetStatesFromCountry @p0", countryIso
);
Теперь скажем, что мы хотим выполнить еще одну хранимую процедуру с двумя параметрами:
var countryIso = "AR"; //Argentina
var stateIso = "RN"; //Río Negro
var citiesFromRioNegro = context.States.SqlQuery(
"dbo.GetCitiesFromState @p0, @p1", countryIso, stateIso
);
Обратите внимание, что мы используем индексирование имен для параметров. Это связано с тем, что Entity Framework будет обертывать эти параметры как объекты DbParameter для вас, чтобы избежать проблем с SQL-инъекциями.
Надеюсь, что этот пример поможет!
Ответ 10
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();
}
Ответ 11
Это работает для меня в коде в первую очередь. Возвращает список с соответствующим свойством модели представления (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();
Обновлено для контекста
Контекст является экземпляром класса, который наследует DbContext, как показано ниже.
public class ApplicationDbContext : DbContext
{
public DbSet<City> City { get; set; }
}
var Context = new ApplicationDbContext();
Ответ 12
Бесшумный пассажир имеет проект, который позволяет возвращать несколько наборов результатов из хранимой процедуры, используя инфраструктуру сущности. Один из его примеров ниже....
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>();
}
Ответ 13
если вы хотите передать параметры таблицы в хранимую процедуру, вам необходимо установить свойство 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();
Ответ 14
Это то, что 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);
}
Ответ 15
Когда 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.
Ответ 16
Я обнаружил, что вызов хранимых процедур в подходе Code First не удобен. Я предпочитаю использовать 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);
Я считаю, что второй кусок кода проще для понимания.
Ответ 17
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();
}
Ответ 18
Ничего не нужно делать... когда вы создаете 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; }
}
Ответ 19
Использование MySql и Entity Framework Code Первый подход:
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();