麻烦将参数传递给LinqToSql存储过程

时间:2010-05-05 21:13:03

标签: linq-to-sql

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,并且具有orderid的单个int参数。我这样称呼上述内容:

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 个答案:

答案 0 :(得分:1)

这不是你应该如何使用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,并且'don' t使用SqlParameter,调用看起来像:

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

(我会先注意,这不是一个SQL注入向量,因为Linq to SQL将花括号变成了参数化查询。)

答案 1 :(得分:1)

答案 2 :(得分:1)

有同样的问题。以下方法对我有用。

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

答案 3 :(得分:0)

我确信有更好的方法可以做到这一点......但目前正在运作:

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

它有点脆弱,因为你的参数必须以正确的顺序设置,而且它可能会冒犯某些......但它确实实现了目标。

答案 4 :(得分:0)

您可以改用:

新的SqlParameter {ParameterName =“UserID”,Value = txtuserid.Text}

System.7Data.SqlClient中的这个等价物:

SqlParameter [] param = new SqlParameter [2]; param [0] = new SqlParameter(“@ UserID”,txtuserid)