问题
I'd like to pass a two-column table-valued parameter (TVP) to an ISQLQuery
:
var sql = "INSERT INTO MovieRatings (PersonID, MovieID, Score) " +
"SELECT :personID, o.movieID, o.score " +
"FROM :scoreObject o";
var query = session.CreateSQLQuery(sql);
query.SetInt32("personID", fred.ID);
query.SetParameterList("scoreObject", fredsRatings.Select(r => new {
movieID = r.Movie.ID,
score = r.Score
}).ToArray() /*, Optional IType hint here */);
query.ExecuteUpdate();
When I do this (or try to hint the IType
as NHibernateUtil.Object
or NHibernateUtil.Class
), NHibernate complains:
NHibernate.HibernateException
: Could not determine a type for class:<>f__AnonymousType5`2[[System.Int32],[System.String]]
It also complains if I try to make a struct
with properties for movieID
and score
and make an array of those instead of anonymous objects. The only thing that changes is the type it "could not determine."
Microsoft seems to say that a TVP can have whatever columns you want:
Passing a Table-Valued Parameter to a Parameterized SQL Statement
The following example demonstrates how to insert data into the
dbo.Categories
table by using anINSERT
statement with aSELECT
subquery that has a table-valued parameter as the data source. When passing a table-valued parameter to a parameterized SQL statement, you must specify a type name for the table-valued parameter by using the new TypeName property of a SqlParameter. ThisTypeName
must match the name of a compatible type previously created on the server. The code in this example uses theTypeName
property to reference the type structure defined indbo.CategoryTableType
.// Assumes connection is an open SqlConnection. using (connection) { // Create a DataTable with the modified rows. DataTable addedCategories = CategoriesDataTable.GetChanges( DataRowState.Added); // Define the INSERT-SELECT statement. string sqlInsert = "INSERT INTO dbo.Categories (CategoryID, CategoryName)" + " SELECT nc.CategoryID, nc.CategoryName" + " FROM @tvpNewCategories AS nc;" // Configure the command and parameter. SqlCommand insertCommand = new SqlCommand( sqlInsert, connection); SqlParameter tvpParam = insertCommand.Parameters.AddWithValue( "@tvpNewCategories", addedCategories); tvpParam.SqlDbType = SqlDbType.Structured; tvpParam.TypeName = "dbo.CategoryTableType"; // Execute the command. insertCommand.ExecuteNonQuery(); }
Is there a way to convince NHibernate to make a TVP with named columns? I'd like to avoid writing my own IType.
回答1:
Remondo has a novel solution to this problem: Add the TVP definition to the transaction with a SqlParameter
from the Microsoft library.
Edit to follow with sample code for the query in the question.
来源:https://stackoverflow.com/questions/46244598/how-can-i-get-nhibernate-to-make-a-multicolumn-table-valued-parameter