【问题标题】:Attempting to Modify Dapper to Support SQL Server CE's ntext type尝试修改 Dapper 以支持 SQL Server CE 的 ntext 类型
【发布时间】:2015-07-30 23:49:45
【问题描述】:

我需要在 Dapper 中支持 SQL Server CE 的 ntext 类型。这里有一个线程描述了这个问题: https://code.google.com/p/dapper-dot-net/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Summary&groupby=&sort=&id=110

我尝试修改 Dapper 以使用类似于 PetaPoco 中使用的方法的解决方案: https://github.com/cyotek/PetaPoco/commit/ea13add473be3899ebb73b463d2aff98f8d6d06e

在查看了 Dapper 的源代码后,我决定尝试这样做的一个好方法可能是修改 DbString 类。我将 AddParameter(IDbCommand command, string name) 方法(从第 3120 行开始)更改为以下内容:

public void AddParameter(IDbCommand command, string name)
{
            if (IsFixedLength && Length == -1)
            {
                throw new InvalidOperationException("If specifying IsFixedLength,  a Length must also be specified");
            }
            var param = command.CreateParameter();
            param.ParameterName = name;
            param.Value = (object)Value ?? DBNull.Value;
            if (Length == -1 && Value != null && Value.Length <= 4000)
            {
                param.Size = 4000;
            }
            else
            {
                param.Size = Length;
            }
            param.DbType = IsAnsi ? (IsFixedLength ? DbType.AnsiStringFixedLength : DbType.AnsiString) : (IsFixedLength ? DbType.StringFixedLength : DbType.String);

            if (param.Value != null)
            {
                if (param.Value.ToString().Length + 1 > 4000 && param.GetType().Name == "SqlCeParameter")
                {
                    param.GetType().GetProperty("SqlDbType").SetValue(param, System.Data.SqlDbType.NText, null);  
                }
            }

            command.Parameters.Add(param);
}

我的编辑是检查类型并尝试将其更改为ntext 的底部部分。但是,当我运行此代码时,IIS Express 崩溃并且 asp.net 没有给我任何有用的调试信息。我尝试在调试器中运行它,但遇到了与堆损坏相关的错误。

我在这里走错了吗?有没有更好的方法在 Dapper 中尝试这样的事情?还是因为缓存和/或 IL 的生成方式而无法正常工作?如果我可以让它工作,我希望为它创建一个拉取请求,但我正在罢工。


更新 - 我找到了一种可能的解决方案。我在DynamicParameters 类的AddParameters(IDbCommand command, SqlMapper.Identity identity) 方法中添加了一些代码。该方法的最后几行现在为:

if (s != null)
{
    if (s.Length + 1 > 4000 && p.GetType().Name == "SqlCeParameter")    
    {
        p.GetType().GetProperty("SqlDbType").SetValue(p, SqlDbType.NText, null);
        p.Size = s.Length;
    }
}
if (add)
{
    command.Parameters.Add(p);
}
param.AttachedParam = p;

为了使用这个解决方案,我必须将我的参数添加为 DynamicParameters。所以它有效,但不是以最有用的方式。我仍在寻找更好的解决方案。

如果我创建拉取请求,Dapper 开发人员是否会考虑将其作为补丁包含在内?

【问题讨论】:

  • “如果我创建拉取请求,Dapper 开发人员会考虑将这种东西作为补丁包含进来吗?”我会在 github 网站上问这个问题。虽然有可能,但这个问题可能永远不会在这里出现。

标签: sql-server-ce dapper


【解决方案1】:

在任何属性包上试试这个扩展方法:

    public static class DynamicParametersExtensions
{
    public static DynamicParameters AsDynamic(this object propertyBag) {
        var parameters = new DynamicParameters();
        foreach (var property in propertyBag.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
            var propertyValue = property.GetValue(propertyBag);
            var propertyValueAsString = propertyValue as string;
            if (propertyValueAsString != null && propertyValueAsString.Length >= 4000) {
                parameters.Add(property.Name, new DbString {
                    Value = propertyValueAsString,
                    Length = propertyValueAsString.Length
                });
            } else {
                parameters.Add(property.Name, propertyValue);
            }
        }
        return parameters;
    }
}

使用示例:

connection.Execute(@"UPDATE MyTable SET NTextColumn=@NTextColumn", new { value.NTextColumn }.AsDynamic()); 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    相关资源
    最近更新 更多