Ошибка передачи параметра в хранимую процедуру LinqToSql - PullRequest
2 голосов
/ 06 мая 2010
public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
        {
            Type genericType = typeof(T);

            string commandthing = genericType.Name.Replace("Result", "");
            //_db is my Linq To Sql database
            return _db.ExecuteQuery<T>(commandthing, parameters).AsEnumerable();
        }

Хранимая процедура называется GetOrder и имеет единственный параметр int orderid. Я звоню выше, вот так:

SqlParameter parm1 = new SqlParameter("@orderid", SqlDbType.Int);
                parm1.Value = 123;
 var results =
                    _session.ExecuteStoredProcedure<GetOrderResult>(parm1).Single();

Я получаю следующую ошибку: Параметр запроса не может иметь тип 'System.Data.SqlClient.SqlParameter'

Мысли? Или я просто упускаю что-то очевидное?

Обновление: Я пытаюсь сделать это настолько универсальным, насколько это возможно ... В настоящее время я думаю, что мне придется сделать несколько строковых уловок для создания текста и параметров ExecuteQuery.

Обновление: Публикация ниже моего интерфейса сеанса и моей реализации интерфейса Linq to Sql ... надеюсь, это прояснит то, что я пытаюсь сделать

 public interface ISession : IDisposable
    {
        void CommitChanges();
        void Delete<T>(Expression<Func<T, bool>> expression) where T : class;
        void Delete<T>(T item) where T : class;
        void DeleteAll<T>() where T : class;
        T Single<T>(Expression<Func<T, bool>> expression) where T : class;
        IQueryable<T> All<T>() where T : class;
        void Add<T>(T item) where T : class;
        void Add<T>(IEnumerable<T> items) where T : class;
        void Update<T>(T item) where T : class;
        IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters);

    }
public class LinqToSqlSession : ISession
    {
        public readonly Db _db;
        public LinqToSqlSession()
        {
            _db = new Db(ConfigurationManager.ConnectionStrings[Environment.MachineName].ConnectionString);
        }

        public void CommitChanges()
        {
            _db.SubmitChanges();
        }
        /// <summary>
        /// Gets the table provided by the type T and returns for querying
        /// </summary>
        private Table<T> GetTable<T>() where T : class
        {
            return _db.GetTable<T>();
        }


        public void Delete<T>(Expression<Func<T, bool>> expression) where T : class
        {

            var query = All<T>().Where(expression);
            GetTable<T>().DeleteAllOnSubmit(query);
        }

        public void Delete<T>(T item) where T : class
        {
            GetTable<T>().DeleteOnSubmit(item);
        }

        public void DeleteAll<T>() where T : class
        {
            var query = All<T>();
            GetTable<T>().DeleteAllOnSubmit(query);
        }



        public void Dispose()
        {
            _db.Dispose();
        }

        public T Single<T>(Expression<Func<T, bool>> expression) where T : class
        {
            return GetTable<T>().SingleOrDefault(expression);
        }

        public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
        {
            Type genericType = typeof(T);

            string commandstring = genericType.Name.Replace("Result", "");
            //_db is my Linq To Sql database

            return _db.ExecuteQuery<T>(commandstring, parameters).AsEnumerable();
        }

        public IQueryable<T> All<T>() where T : class
        {
            return GetTable<T>().AsQueryable();
        }

        public void Add<T>(T item) where T : class
        {
            GetTable<T>().InsertOnSubmit(item);
        }
        public void Add<T>(IEnumerable<T> items) where T : class
        {
            GetTable<T>().InsertAllOnSubmit(items);
        }
        public void Update<T>(T item) where T : class
        {
            //nothing needed here
        }
}

Ответы [ 5 ]

1 голос
/ 07 июня 2012

Была такая же проблема. Следующий подход сработал 4 мне.

public interface IBusinessEntityRepository
{
    .......
    object CallStoredProcedure(string storedProcedureName, object[] parameters);
}

реализация в моем linqtosql GenericLinqRepository

public object CallStoredProcedure(string storedProcedureName, object[] parameters)
{
    DataContext dataContext = GetCurrentDataContext();
    MethodInfo method = dataContext.GetType().GetMethod(storedProcedureName);
    return method.Invoke(dataContext, parameters);
}
1 голос
/ 06 мая 2010
1 голос
/ 06 мая 2010

Это не то, как вы должны соединять хранимые процедуры с Linq-to-SQL. Вы должны расширить DataContext и использовать ExecuteMethodCall вместо:

Взято из MSDN :

public partial class MyDataContext
{
    [Function()]
    public IEnumerable<Customer> CustomerById(
        [Parameter(Name = "CustomerID", DbType = "NChar(5)")]
        string customerID)
    {
        IExecuteResult result = this.ExecuteMethodCall(this,
            ((MethodInfo)(MethodInfo.GetCurrentMethod())),
            customerID);
        return (IEnumerable<Customer>)(result.ReturnValue);
    }
}

Если вы действительно должны выполнить sproc в качестве запроса (настоятельно рекомендуется , а не ), то вы должны предварять команду EXEC и не использовать SqlParameter либо вызов будет выглядеть так:

var results = context.ExecuteQuery<MyResult>("EXEC usp_MyProc {0}, {1}",
    custID, custName);

(И я отмечу, что это не вектор SQL-инъекции, потому что Linq to SQL превращает фигурные скобки в параметризованный запрос.)

0 голосов
/ 13 января 2011

Вы можете использовать это вместо:

new SqlParameter {ParameterName = "UserID", Value = txtuserid.Text}

Этот эквивалент в System.Data.SqlClientto:

SqlParameter [] param = новый SqlParameter [2];param [0] = новый SqlParameter ("@ UserID", txtuserid)

0 голосов
/ 06 мая 2010

Я уверен, что есть лучший способ сделать это ... но сейчас это работает:

    public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
    {
        Type genericType = typeof(T);

        StringBuilder sb=new StringBuilder();
        sb.Append("EXEC ");
        sb.Append(genericType.Name.Replace("Result", " " ));
        for (int i = 0; i < parameters.Count(); i++)
        {
            sb.Append("{" + i.ToString() + "} ");
        }
        string commandstring = sb.ToString();

        return _db.ExecuteQuery<T>(commandstring, parameters);
    }

Немного хрупко, потому что ваши параметры должны быть установлены в правильном порядке, и это, возможно, оскорбительно для некоторых ... но это действительно достигает цели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...