首页 > 解决方案 > 如何使用EF fluent api将sql server上的用户定义类型映射到模型?

问题描述

在 sql server 上,我制作了这样的用户定义类型

CREATE TYPE [TowarType] AS TABLE(
    [GIDTyp] [int] NULL,
    [GIDNumer] [int] NULL,
    [Kod] [varchar](255) NULL
)

在 c# 中,它由模型表示

public class TowaryType
{
    public int GIDTyp { get; set; }
    public int GIDNumer { get; set; }
    public string Kod { get; set; }
}

我还有一个以这种类型为参数的存储过程,这个过程返回一个sql查询结果表,我想用实体框架调用这个存储过程并检索结果。我这样做

   public List<ReturnModelType> GetResultFromSqlQuery<ReturnModelType>(string sqlQuery, params object[] parameters)
    {
        var result = this.Database.SqlQuery(typeof(ReturnModelType), sqlQuery, parameters);
        List<ReturnModelType> localModels = new List<ReturnModelType>();
        foreach (var o in result)
        {

            ReturnModelType m = (ReturnModelType)o;
            localModels.Add(m);
        }
        return localModels;
    }

//

 var result = _context.GetResultFromSqlQuery<ResultModel>(
                        "exec StanTowarow @Magazyny, @Towary, @Dzien", 
                        new SqlParameter("@Magazyny", magazynyParams),
                        new SqlParameter("@Towary", towaryParams),
                        new SqlParameter("@Dzien", dzien)

                    );

但我得到 System.ArgumentException,它说我的用户定义类型不存在映射。

我认为你应该用流畅的 API 映射它,但我不知道如何,谁能指出我正确的方向?

标签: c#sqlentity-frameworkuser-defined-typesef-fluent-api

解决方案


经过一番阅读,我设法解决了我的问题。我的问题是需要正确配置的 SqlParameter 对象来正确传递我的表值用户定义参数。我创建了一个函数,它使用我的模型中的对象列表并返回一个正确配置的 SqlParameter。

这是我的用户定义参数

CREATE TYPE [TowarType] AS TABLE(
    [GIDTyp] [int] NULL,
    [GIDNumer] [int] NULL,
    [Kod] [varchar](255) NULL
)

// 这里是这个参数的ac#模型

 public class TowaryType
{
    public int GIDTyp { get; set; }
    public int GIDNumer { get; set; }
    public string Kod { get; set; }
}

我创建了一个模型列表并用数据填充它

List<TowaryType> modelList = new List<TowaryType>();
//populating code here

之后我需要从该列表中创建一个 SqlParameter ,所以我在我的 applicationDbContext 中创建了一个方法来为我做这件事:

public SqlParameter GetTableValuedParameter<Model>(List<Model> valueTable, string typeName, string paramName)
        {
            if(valueTable == null || valueTable.Count == 0)
                throw new Exception("Cant be empty or null.");

            DataTable dataTable = new DataTable();

            var header = valueTable.First().GetType().GetProperties();

            foreach (var propertyInfo in header)
            {
                dataTable.Columns.Add(propertyInfo.Name);
            }

            foreach (var model in valueTable)
            {
                DataRow dataRow = dataTable.NewRow();
                var properties = model.GetType().GetProperties();
                foreach (var propertyInfo in properties)
                {
                    dataRow[propertyInfo.Name] = propertyInfo.GetValue(model);
                }

                dataTable.Rows.Add(dataRow);
            }

            var sqlParameter = new SqlParameter(paramName, SqlDbType.Structured);
            sqlParameter.Value = dataTable;
            sqlParameter.TypeName = typeName;

            return sqlParameter;
        }

之后我所要做的就是在我想要传递给我的存储过程的模型列表上调用这个函数,然后调用我的存储过程

var param1 = _context.GetTableValuedParameter(magazynyParams, "MagazynType", "@Magazyny");
var param2 = _context.GetTableValuedParameter(towaryParams, "TowarType", "@Towary");

                var result = _context.GetResultFromSqlQuery<ResultModel>(
                    "exec StanTowarow @Magazyny, @Towary, @Dzien", 
                    param1,
                    param2,
                    new SqlParameter("@Dzien", dzien)

推荐阅读