2012-02-09 17 views
4


私の問題はこれです。データコンテキストExecuteQuery(文字列クエリ、paramsオブジェクト[]パラメータ)(here)を使用している場合、どのような形や形であれnullを渡すことはできません。これを開始したパラメータはSQLのnvarcharパラメータで、nullを許可する必要があります。DataContext.ExecuteQuery <TEntity>とnull値

答えとしてマークされた "use DBNull.Value"を持っていたstackoverflowでこのarticleを読んでいたので、私はそれを試みましたが、何もしませんでした。 。ここで

var db = new Test1DataContext(Properties.Settings.Default.TestConnectionString); 
var query = "EXEC UpInsertTest4 {0}, {1}"; 

// Works fine 
var list1 = new List<object> { 1, "1" }; 
db.ExecuteQuery<UpInsertTest4Result>(query, list1.ToArray()); 

// Doesn't work 
var list2 = new List<object> { 1, DBNull.Value }; 
db.ExecuteQuery<UpInsertTest4Result>(query, list2.ToArray()); 

は私が受け取る様々なエラーです:

null    : A query parameter cannot be of type 'System.Object'. 
default(string)  : A query parameter cannot be of type 'System.Object'. 
DBNull.Value  : Unexpected type code: DBNull (which give this as a stack trrace) 
 

at System.Data.Linq.SqlClient.SqlTypeSystem.Sql2005Provider.From(Type type, Nullable`1 size) 
    at System.Data.Linq.SqlClient.SqlTypeSystem.Sql2008Provider.From(Type type, Nullable`1 size) 
    at System.Data.Linq.SqlClient.SqlTypeSystem.ProviderBase.From(Type type) 
    at System.Data.Linq.SqlClient.SqlTypeSystem.ProviderBase.From(Object o) 
    at System.Data.Linq.SqlClient.SqlFactory.ValueFromObject(Object value, Type clrType, Boolean isClientSpecified, Expression sourceExpression) 
    at System.Data.Linq.SqlClient.QueryConverter.VisitConstant(ConstantExpression cons) 
    at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) 
    at System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp) 
    at System.Data.Linq.SqlClient.QueryConverter.VisitUserQuery(String query, Expression[] arguments, Type resultType) 
    at System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc) 
    at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) 
    at System.Data.Linq.SqlClient.QueryConverter.ConvertOuter(Expression node) 
    at System.Data.Linq.SqlClient.SqlProvider.BuildQuery(Expression query, SqlNodeAnnotations annotations) 
    at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) 
    at System.Data.Linq.DataContext.ExecuteMethodCall(Object instance, MethodInfo methodInfo, Object[] parameters) 
    at System.Data.Linq.DataContext.ExecuteQuery[TResult](String query, Object[] parameters) 
    at ConsoleApplication1.Program.Main(String[] args) in E:\TestBed\Testbed\ConsoleApplication1\Program.cs:line 36 
    at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 

 
ここ

は、私は(これは単なる概念をテストすることです、ノート)を実行しようとしていたサンプルコードです

私が読んだことから、私はこれとの戦いの戦いを戦うことができました!これは私の最後の溝の試みです!

多くのありがとう、
クリス。

+0

)は、あなたが新しいのNullable (にそれを設定しようとしたことがありますか? –

+0

はい、私は持っている必要があります、ごめんなさい!文字列コンパイル時のエラーでは機能しません: "型 '文字列'は、汎用型またはメソッド 'System.Nullable 'でパラメータ 'T'として使用するには、 。 – Bertie

答えて

5

あなたはこのようにそれに何かを行うことができます:

db.ExecuteQuery<UpInsertTest4Result>(string.Format(query,1,"null")); 

更新

はい、私は解決策をテストしました。 @p1=N'null'は含まれません。私はsqlを文字列として直接使用しているからです。だから概念の教授。

ストア手順:出力をテストするための

CREATE PROCEDURE testas 
@test1 INT, 
@test2 INT 
AS 
SELECT 1 test 

クラス:

public class testout 
{ 
    public int test { get; set; } 
} 

LINQクエリDBのコンテキストで:

var query="exec testas {0}, {1}"; 
db.ExecuteQuery<testout>(string.Format(query,"0","null")); 

あなたはlinqpadに見える場合は、SQLが出力されますこのように:

exec testas 0, null 

文字列形式は文字列を変更するだけです。これは、これを書いてと同じようになります:

db.ExecuteQuery<testout>("exec testas 0, null") 
+0

ハ、そうすることができます!そして、私が見た1つの答えはそれを示唆していません!私は文字列、int&ビットnull可能な列とこれまでのようにそれを試してみました!うまくやった! – Bertie

+0

それはかなり奇妙で、あなたが期待するものではありません。喜んでお手伝いします。 – Arion

+0

解決方法を試しましたか?出力されるSQLには、 '、@ p1 = null'の代わりに'、@ p1 = N'null''のようなものが含まれます。 – UserControl

0

は、このクリスを試してみてください。

void Main() 
{ 
    var db = new Test1DataContext(Properties.Settings.Default.TestConnectionString); 
    db.UpInsertTest4Result(1,"1"); 
    db.UpInsertTest4Result(1,null); 
    db.UpInsertTest4Result(null,"1"); 
    db.UpInsertTest4Result(null,null); 
} 

public class Test1DataContext : DataContext 
{ 
    public Test1DataContext(string connStr) : base(connStr) { } 

    [Function(Name = "UpInsertTest4")] 
    public IEnumerable<UpInsertTest4Result> UpInsertTest4Result(
    [Parameter(Name = "par1", DbType = "Int")] int? par1, 
    [Parameter(Name = "par2", DbType = "VarChar")] string par2) 
    { 
     var result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), par1,par2); 

     return (IEnumerable<UpInsertTest4Result>)result.ReturnValue; 
    } 
} 
1

私は同じ問題を抱えていたし、私はこのフォーラムで解決策を見つけた:https://social.msdn.microsoft.com/Forums/en-US/20b318bc-32cf-466b-972e-6cd37e625cd6/a-query-parameter-cannot-be-of-the-type-systemobject?forum=linqprojectgeneral

基本的には、目標をパラメータを分析し、すべてのnullパラメータを要求に直接置き換える拡張メソッドを作成することです。例: "EXEC MyStoredProcedure {0}、{1}、{2}、{3}"は、アレイパラメータから削除されます。ここで

はメソッドです:

internal static IEnumerable<TResult> ExecuteQueryNullSafe<TResult>(this System.Data.Linq.DataContext context, string command, params object[] parameters) 
{ 
    var list = new List<object>(); 
    var listVals = new List<bool>(); 

    for (int x = 0; x < parameters.Count(); x++) 
    { 
    if (parameters[x] == null || parameters[x] is System.DBNull) 
    { 
     command = command.Replace("{" + x + "}", "NULL"); 
     listVals.Add(false); 
    } 
    else 
    { 
     list.Add(parameters[x]); 
     listVals.Add(true); 
    } 
    } 

    int nextId = 0; 
    for (int i = 0; i < listVals.Count; i++) 
    { 
    var isUsed = listVals[i]; 
    if (!isUsed) 
     continue; 
    if (nextId != i) 
     command = command.Replace("{" + i.ToString() + "}", "{" + nextId.ToString() + "}"); 
    nextId++; 
    } 

    return context.ExecuteQuery<TResult>(command, list.ToArray()); 
}