Monday, 1 December 2014

Entity Framework (Code First): the easy way to run stored procedures

An ordinal way to execute stored procedure in EF CF is something like this:


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public Product GetProduct(int id)
{
    Product product = null;
 
    using (var context = new NorthwindData())
    {
        string query = "Product_GetByID @productId";
        SqlParameter productId = new SqlParameter("@productId", id);
 
        product = context.Database.SqlQuery<Product>(query, productId).FirstOrDefault();
    }
 
    return product;
}

If you have more parameters for SP, you should specify all of them. Sometimes it's boring... So, I wrote several simple extensions toDatabase class to simplify this task.

See code below how GetProduct method will look like when using extensions:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public Product GetProduct(int id)
{
    Product product = null;
 
    using (var context = new NorthwindData())
    {
        product = context.Database.SqlQuerySmart<Product>("Product_GetByID"new
        {
            productId = id
        }).FirstOrDefault();
    }
 
    return product;
}

As you can see, you just create anonymous type with fields that has names exactly as parameters of SP and extension takes care about correct SQL code and other things. But, extension works only in simple cases, when there are no OUT parameters in SP.

Code of extension provided below, enjoy!

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Reflection;
 
namespace HennadiyKurabko.Data.EF
{
    public static class Extensions
    {
        public static int ExecuteSqlCommandSmart(this Database self, string storedProcedure,object parameters = null)
        {
            if (self == null)
                throw new ArgumentNullException("self");
            if (string.IsNullOrEmpty(storedProcedure))
                throw new ArgumentException("storedProcedure");
 
            var arguments = PrepareArguments(storedProcedure, parameters);
            return self.ExecuteSqlCommand(arguments.Item1, arguments.Item2);
        }
 
        public static IEnumerable<TElement> SqlQuerySmart<TElement>(this Database self, string storedProcedure, object parameters = null)
        {
            if (self == null)
                throw new ArgumentNullException("self");
            if (string.IsNullOrEmpty(storedProcedure))
                throw new ArgumentException("storedProcedure");
 
            var arguments = PrepareArguments(storedProcedure, parameters);
            return self.SqlQuery<TElement>(arguments.Item1, arguments.Item2);
        }
 
        public static IEnumerable SqlQuerySmart(this Database self, Type elementType, string storedProcedure, object parameters = null)
        {
            if (self == null)
                throw new ArgumentNullException("self");
            if (elementType == null)
                throw new ArgumentNullException("elementType");
            if (string.IsNullOrEmpty(storedProcedure))
                throw new ArgumentException("storedProcedure");
 
            var arguments = PrepareArguments(storedProcedure, parameters);
            return self.SqlQuery(elementType, arguments.Item1, arguments.Item2);
        }
 
        private static Tuple<stringobject[]> PrepareArguments(string storedProcedure, object parameters)
        {
            var parameterNames = new List<string>();
            var parameterParameters = new List<object>();
 
            if (parameters != null)
            {
                foreach (PropertyInfo propertyInfo in parameters.GetType().GetProperties())
                {
                    string name = "@" + propertyInfo.Name;
                    object value = propertyInfo.GetValue(parameters, null);
 
                    parameterNames.Add(name);
                    parameterParameters.Add(new SqlParameter(name, value ?? DBNull.Value));
                }
            }
 
            if (parameterNames.Count > 0)
                storedProcedure += " " string.Join(", ", parameterNames);
 
            return new Tuple<stringobject[]>(storedProcedure, parameterParameters.ToArray());
        }
    }
}

Shout it

kick it on DotNetKicks.com

No comments:

Post a Comment

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...