How to call Stored Procedure in Entity Framework 6 (Code-First)?

前端 未结 21 2045
滥情空心
滥情空心 2020-11-22 05:04

I am very new to Entity Framework 6 and I want to implement stored procedures in my project. I have a stored procedure as follows:

ALTER PROCEDURE [dbo].[ins         


        
相关标签:
21条回答
  • 2020-11-22 06:04

    Using your example, here are two ways to accomplish this:

    1 - Use Stored procedure mapping

    Note that this code will work with or without mapping. If you turn off mapping on the entity, EF will generate an insert + select statement.

    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 - Call the stored procedure directly

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

    I recommend using the first approach, as you can work with the department object directly and not have to create a bunch of SqlParameter objects.

    0 讨论(0)
  • 2020-11-22 06:05

    Nothing have to do... when you are creating dbcontext for code first approach initialize namespace below the fluent API area make list of sp and use it another place where you want.

    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 讨论(0)
  • 2020-11-22 06:06

    All you have to do is create an object that has the same property names as the results returned by the stored procedure. For the following stored procedure:

        CREATE PROCEDURE [dbo].[GetResultsForCampaign]  
        @ClientId int   
        AS
        BEGIN
        SET NOCOUNT ON;
    
        SELECT AgeGroup, Gender, Payout
        FROM IntegrationResult
        WHERE ClientId = @ClientId
        END
    

    create a class that looks like:

        public class ResultForCampaign
        {
            public string AgeGroup { get; set; }
    
            public string Gender { get; set; }
    
            public decimal Payout { get; set; }
        }
    

    and then call the procedure by doing the following:

        using(var context = new DatabaseContext())
        {
                var clientIdParameter = new SqlParameter("@ClientId", 4);
    
                var result = context.Database
                    .SqlQuery<ResultForCampaign>("GetResultsForCampaign @ClientId", clientIdParameter)
                    .ToList();
        }
    

    The result will contain a list of ResultForCampaign objects. You can call SqlQuery using as many parameters as needed.

    0 讨论(0)
  • 2020-11-22 06:06

    You can now also use a convention I created which enables invoking stored procedures (including stored procedures returning multiple resultsets), TVFs and scalar UDFs natively from EF.

    Until Entity Framework 6.1 was released store functions (i.e. Table Valued Functions and Stored Procedures) could be used in EF only when doing Database First. There were some workarounds which made it possible to invoke store functions in Code First apps but you still could not use TVFs in Linq queries which was one of the biggest limitations. In EF 6.1 the mapping API was made public which (along with some additional tweaks) made it possible to use store functions in your Code First apps.

    Read more

    I pushed quite hard for the past two weeks and here it is – the beta version of the convention that enables using store functions (i.e. stored procedures, table valued functions etc.) in applications that use Code First approach and Entity Framework 6.1.1 (or newer). I am more than happy with the fixes and new features that are included in this release.

    Read more.

    0 讨论(0)
  • 2020-11-22 06:06
    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 讨论(0)
  • 2020-11-22 06:08

    This is what EF (DB first) generates in the DbContext class:

    public ObjectResult<int> Insert_Department(string department)
    {
        var departmentParameter = new ObjectParameter("department", department);
    
        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<int>("insert_department", departmentParameter);
    }
    
    0 讨论(0)
提交回复
热议问题