我有一个像这样的存储过程:
CREATE PROCEDURE [dbo].[Organisation_Insert]
@OrganisationXId uniqueidentifier
,@Enabled bit
,@Timezone nvarchar(50)
,@MinimumValue float
,@Rules ReminderRuleType READONLY ...
ReminderRuleType是用户定义的类型。
在我的应用中,我有这个:
class OrganisationDTO
{
private readonly IOrganisationDocument _orgDoc;
public long OrganisationId { get { return _orgDoc.OrganisationId; } }
public Guid OrganisationXId { get { return _orgDoc.OrganisationXId; } }
public string TimeZone { get { return _orgDoc.TimeZone; } }
public bool Enabled { get { return _orgDoc.Enabled; } }
public decimal MinimumValue { get { return _orgDoc.MinimumValue; } }
public RuleTableValuedParameters Rules { get; private set; }
public OrganisationDTO(IOrganisationDocument orgDoc)
{
_orgDoc = orgDoc;
Rules = new RuleTableValuedParameters("@Rules", _orgDoc.Rules);
}
}
RuleTableValuedParameters实现了具有AddParameters方法的SqlMapper.IDynamicParameters。
执行查询时,永远不会传递@Rules参数(使用SQLProfiler)。我还可以看到从不调用AddParameters。
这可能吗?
由于
答案 0 :(得分:2)
这是一个基于您的代码的简化示例,显示它工作得很好;正确调用AddParameters
,并将值传递给存储过程。作为旁注:如果您使用DataTable
作为您的TVP,则该库直接支持,无需其他代码。
public void SO29596645_TvpProperty()
{
try { connection.Execute("CREATE TYPE SO29596645_ReminderRuleType AS TABLE (id int NOT NULL)"); }
catch { }
connection.Execute(@"create proc #SO29596645_Proc (@Id int, @Rules SO29596645_ReminderRuleType READONLY)
as begin select @Id + ISNULL((select sum(id) from @Rules), 0); end");
var obj = new SO29596645_OrganisationDTO();
int val = connection.Query<int>("#SO29596645_Proc", obj.Rules, commandType: CommandType.StoredProcedure).Single();
// 4 + 9 + 7 = 20
val.IsEqualTo(20);
}
class SO29596645_RuleTableValuedParameters : Dapper.SqlMapper.IDynamicParameters {
private string parameterName;
public SO29596645_RuleTableValuedParameters(string parameterName)
{
this.parameterName = parameterName;
}
public void AddParameters(IDbCommand command, Dapper.SqlMapper.Identity identity)
{
Console.WriteLine("> AddParameters");
SqlCommand lazy = (SqlCommand)command;
lazy.Parameters.AddWithValue("Id", 7);
DataTable table = new DataTable {
Columns = {{"Id", typeof(int)}},
Rows = {{4}, {9}}
};
lazy.Parameters.AddWithValue("Rules", table);
Console.WriteLine("< AddParameters");
}
}
class SO29596645_OrganisationDTO
{
public SO29596645_RuleTableValuedParameters Rules { get; private set; }
public SO29596645_OrganisationDTO()
{
Rules = new SO29596645_RuleTableValuedParameters("@Rules");
}
}
答案 1 :(得分:2)
这是我创建的完整工作DynamicParameter:
public class OrganisationDynamicParameter : SqlMapper.IDynamicParameters
{
private readonly IOrganisation _orgModel;
public OrganisationDynamicParameter(IOrganisation orgModel)
{
_orgModel = orgModel;
}
public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
SqlParameter p;
var sqlCommand = (SqlCommand)command;
sqlCommand.CommandType = CommandType.StoredProcedure;
p = sqlCommand.Parameters.Add("@OrganisationXId", SqlDbType.UniqueIdentifier);
p.Value = _orgModel.OrganisationXId;
p = sqlCommand.Parameters.Add("@Enabled", SqlDbType.Bit);
p.Value = _orgModel.Enabled;
p = sqlCommand.Parameters.Add("@Timezone", SqlDbType.NVarChar, 50);
p.Value = _orgModel.TimeZone;
p = sqlCommand.Parameters.Add("@MinimumValue", SqlDbType.Float);
p.Value = _orgModel.MinimumValue;
List<SqlDataRecord> ruleList = _orgModel.Rules.Select(MapRuleData).ToList();
if (ruleList.Count > 0)
{
p = sqlCommand.Parameters.Add("@Rules", SqlDbType.Structured);
p.Direction = ParameterDirection.Input;
p.TypeName = "ReminderRuleType";
p.Value = ruleList;
}
}
protected SqlDataRecord MapRuleData(IReminderRule value)
{
var rec = new SqlDataRecord(new[]
{
new SqlMetaData("RuleId", SqlDbType.BigInt),
new SqlMetaData("OrganisationId", SqlDbType.BigInt),
new SqlMetaData("Name", SqlDbType.NVarChar, 200),
new SqlMetaData("OffsetDays", SqlDbType.Int),
new SqlMetaData("SubjectTemplate", SqlDbType.NVarChar, -1),
new SqlMetaData("BodyTemplate", SqlDbType.NVarChar, -1)
});
rec.SetInt64(0, value.RuleId);
rec.SetInt64(1, value.OrganisationId);
rec.SetString(2, value.Name);
rec.SetInt32(3, value.OffsetDays);
rec.SetString(4, value.SubjectTemplate);
rec.SetString(5, value.BodyTemplate);
return rec;
}
}
我这样使用它:
public IOrganisation CreateOrganisation(IOrganisation organisation)
{
var dtoOrg = new OrganisationDynamicParameter(organisation);
return ExecuteSPReturningOrganisation("Organisation_Insert", dtoOrg);
}
protected IOrganisation ExecuteSPReturningOrganisation(string query, object parameters)
{
using (IDbConnection con = ConnectionFactory.CreateOpenConnection())
{
using (
SqlMapper.GridReader multi = con.QueryMultiple(query, parameters,
commandType: CommandType.StoredProcedure))
{
OrganisationModel org = multi.Read<OrganisationModel>().SingleOrDefault();
if (org != null)
{
org.Rules = multi.Read<ReminderRuleModel>().ToArray();
}
return org;
}
}
}
干杯