it-swarm.com.de

Wie rufe ich die gespeicherte Prozedur in Entity Framework 6 (Code-First) auf?

Ich bin sehr neu in Entity Framework 6 und möchte gespeicherte Prozeduren in meinem Projekt implementieren. Ich habe eine gespeicherte Prozedur wie folgt:

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 Klasse:

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
}

Mein Problem ist: Wie kann ich die gespeicherte Prozedur aufrufen und Parameter übergeben?

248
Jaan

Sie können eine gespeicherte Prozedur in Ihrer Klasse DbContext wie folgt aufrufen.

this.Database.SqlQuery<YourEntityType>("storedProcedureName",params);

Wenn Ihre gespeicherte Prozedur jedoch mehrere Ergebnismengen als Beispielcode zurückgibt, wird dieser hilfreiche Artikel zu MSDN angezeigt

Gespeicherte Prozeduren mit mehreren Ergebnismengen

237
Alborz

Sie müssen lediglich ein Objekt erstellen, das dieselben Eigenschaftsnamen wie die von der gespeicherten Prozedur zurückgegebenen Ergebnisse hat. Für die folgende gespeicherte Prozedur:

    CREATE PROCEDURE [dbo].[GetResultsForCampaign]  
    @ClientId int   
    AS
    BEGIN
    SET NOCOUNT ON;

    SELECT AgeGroup, Gender, Payout
    FROM IntegrationResult
    WHERE ClientId = @ClientId
    END

erstelle eine Klasse, die so aussieht:

    public class ResultForCampaign
    {
        public string AgeGroup { get; set; }

        public string Gender { get; set; }

        public decimal Payout { get; set; }
    }

rufen Sie dann die Prozedur auf, indem Sie folgendermaßen vorgehen:

    using(var context = new DatabaseContext())
    {
            var clientIdParameter = new SqlParameter("@ClientId", 4);

            var result = context.Database
                .SqlQuery<ResultForCampaign>("GetResultsForCampaign @ClientId", clientIdParameter)
                .ToList();
    }

Das Ergebnis enthält eine Liste von ResultForCampaign Objekten. Sie können SqlQuery mit beliebig vielen Parametern aufrufen.

141
Filipe Leite

Ich habe es mit ExecuteSqlCommand gelöst

Fügen Sie Ihre eigene Methode wie meine in DbContext als Ihre eigenen Instanzen ein:

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);
}

so können Sie eine Methode in Ihrem Code-Behind haben:

[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;
    }
}

das ist mein 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

hoffnung hat dir geholfen

47

Mit Ihrem Beispiel haben Sie zwei Möglichkeiten, dies zu erreichen:

1 - Verwenden Sie die Zuordnung gespeicherter Prozeduren

Beachten Sie, dass dieser Code mit oder ohne Zuordnung funktioniert. Wenn Sie die Zuordnung für die Entität deaktivieren, generiert EF eine Anweisung 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;
     }
}

2 - Rufen Sie die gespeicherte Prozedur direkt auf

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;
     }
}

Ich empfehle die Verwendung des ersten Ansatzes, da Sie direkt mit dem Abteilungsobjekt arbeiten können und nicht mehrere SqlParameter-Objekte erstellen müssen.

19

Sie verwenden MapToStoredProcedures(), was angibt, dass Sie Ihre Entitäten gespeicherten Prozeduren zuordnen. Wenn Sie dies tun, müssen Sie die Tatsache, dass es eine gespeicherte Prozedur gibt, loslassen und context wie gewohnt verwenden. Sowas in den Browser geschrieben ( also nicht getestet )

using(MyContext context = new MyContext())
{
    Department department = new Department()
    {
        Name = txtDepartment.text.trim()
    };
    context.Set<Department>().Add(department);
}

Wenn Sie nur wirklich versuchen, eine gespeicherte Prozedur direkt aufzurufen, verwenden Sie SqlQuery

15
qujck

Sie können jetzt auch eine von mir erstellte Konvention verwenden, mit der gespeicherte Prozeduren (einschließlich gespeicherter Prozeduren, die mehrere Resultsets zurückgeben), TVFs und skalare UDFs nativ von EF aufgerufen werden können.

Bis zur Veröffentlichung von Entity Framework 6.1 konnten Speicherfunktionen (d. H. Tabellenwertfunktionen und gespeicherte Prozeduren) in EF nur verwendet werden, wenn zuerst die Datenbank ausgeführt wurde. Es gab einige Problemumgehungen, die es ermöglichten, Speicherfunktionen in Code First-Apps aufzurufen, aber Sie konnten weiterhin keine TVFs in Linq-Abfragen verwenden, was eine der größten Einschränkungen war. In EF 6.1 wurde die Zuordnungs-API veröffentlicht, die (zusammen mit einigen zusätzlichen Verbesserungen) die Verwendung von Speicherfunktionen in Ihren Code First-Apps ermöglichte.

Weiterlesen

Ich habe in den letzten zwei Wochen viel Druck gemacht und hier ist es - die Beta-Version der Konvention, die es ermöglicht, Speicherfunktionen (dh gespeicherte Prozeduren, Tabellenwertfunktionen usw.) in Anwendungen zu verwenden, die Code First Approach und Entity Framework 6.1.1 verwenden ( oder neuer). Ich bin mehr als zufrieden mit den Korrekturen und neuen Funktionen, die in dieser Version enthalten sind.

Weiterlesen .

12
Pawel

Dies funktioniert für mich, indem Daten aus einer gespeicherten Prozedur abgerufen werden, während ein Parameter übergeben wird.

var param = new SqlParameter("@datetime", combinedTime);
var result = 
        _db.Database.SqlQuery<QAList>("dbo.GetQAListByDateTime @datetime", param).ToList();

_db ist der dbContext

10
Tom Stickel
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;  
10
Shiraj Momin

Schauen Sie sich diesen Link an, der zeigt, wie die Zuordnung von EF 6 mit gespeicherten Prozeduren zum Einfügen, Aktualisieren und Löschen funktioniert: http://msdn.Microsoft.com/en-us/data/dn46867 =

Addition

Hier ist ein großartiges Beispiel für den Aufruf einer gespeicherten Prozedur aus Code First:

Nehmen wir an, Sie müssen eine gespeicherte Prozedur mit einem einzelnen Parameter ausführen, und diese gespeicherte Prozedur gibt eine Reihe von Daten zurück, die mit den Entitätszuständen übereinstimmen.

var countryIso = "AR"; //Argentina

var statesFromArgentina = context.Countries.SqlQuery(
                                      "dbo.GetStatesFromCountry @p0", countryIso
                                                    );

Nehmen wir nun an, wir möchten eine weitere gespeicherte Prozedur mit zwei Parametern ausführen:

var countryIso = "AR"; //Argentina
var stateIso = "RN"; //Río Negro

var citiesFromRioNegro = context.States.SqlQuery(
                            "dbo.GetCitiesFromState @p0, @p1", countryIso, stateIso
                          );

Beachten Sie, dass wir die indexbasierte Benennung für Parameter verwenden. Dies liegt daran, dass Entity Framework diese Parameter als DbParameter-Objekte für Sie einschließt, um SQL-Injection-Probleme zu vermeiden.

Hoffe dieses Beispiel hilft!

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();
}
6

Es funktioniert für mich zuerst am Code. Es wird eine Liste mit der entsprechenden Eigenschaft des Ansichtsmodells zurückgegeben (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();

für den Kontext aktualisiert

Kontext ist die Instanz der Klasse, die DbContext wie folgt erbt.

public class ApplicationDbContext : DbContext
{
    public DbSet<City> City { get; set; }
}

var Context = new  ApplicationDbContext();
4
reza.cse08

Mindless Passenger verfügt über ein Projekt, mit dem mehrere Ergebnismengen aus einem gespeicherten Prozess mithilfe eines Entity-Frameworks zurückgegeben werden können. Eines seiner Beispiele unten ....

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>();
}
1
Dib

wenn Sie Tabellenparameter an gespeicherte Prozeduren übergeben möchten, müssen Sie die TypeName-Eigenschaft für Ihre Tabellenparameter festlegen.

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();
0
trueboroda

Ich fand, dass das Aufrufen von Stored Procedures im Code First-Ansatz nicht bequem ist. Ich bevorzuge stattdessen die Verwendung von Dapper

Der folgende Code wurde mit Entity Framework geschrieben:

var clientIdParameter = new SqlParameter("@ClientId", 4);

var result = context.Database
.SqlQuery<ResultForCampaign>("GetResultsForCampaign @ClientId", clientIdParameter)
.ToList();

Der folgende Code wurde mit Dapper geschrieben:

return Database.Connection.Query<ResultForCampaign>(
            "GetResultsForCampaign ",
            new
            {
                ClientId = 4
            },
            commandType: CommandType.StoredProcedure);

Ich glaube, der zweite Teil des Codes ist einfacher zu verstehen.

0

Nichts zu tun ... Wenn Sie dbcontext für den Code-First-Approach erstellen, initialisieren Sie den Namespace unterhalb des fließenden API-Bereichs.

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; }
}
0
SHUBHASIS

Verwenden von MySQL- und 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();
0
Hari Lakkakula
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();
        }
0
user1883961

Dies ist, was EF (DB first) in der DbContext-Klasse generiert:

public ObjectResult<int> Insert_Department(string department)
{
    var departmentParameter = new ObjectParameter("department", department);

    return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<int>("insert_department", departmentParameter);
}
0
IngoB

Wenn EDMX dieses Mal eine gespeicherte Prozedur in der Tabellenauswahloption erstellt, rufen Sie die gespeicherte Prozedur einfach mit dem prozedierten Namen auf.

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.
0
Shafiq Rabbi