使用Dapper.Net ORM,如何將存儲過程輸出轉換為具體類型?

c#-4.0 dapper metadata sql-server-2008-r2 stored-procedures

使用實體框架我可以從我正在處理的項目的數據庫中的大多數sprocs創建具體的類。但是,某些sprocs使用動態SQL,因此沒有為sproc返回元數據。

所以對於那個sproc,我手動創建了一個具體類,現在想要將sproc輸出映射到這個類並返回這種類型的列表。

使用以下方法,我可以獲得一組對象:

                var results = connection.Query<object>("get_buddies", 
                    new {   RecsPerPage = 100,
                            RecCount = 0,
                            PageNumber = 0,
                            OrderBy = "LastestLogin",
                            ProfileID = profileID,
                            ASC = 1}, 
                        commandType: CommandType.StoredProcedure);

我的具體課包含

[DataContractAttribute(IsReference=true)]
[Serializable()]
public partial class LoggedInMember : ComplexObject
{

   /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.Int16 RowID
    {
        get
        {
            return _RowID;
        }
        set
        {
            OnRowIDChanging(value);
            ReportPropertyChanging("RowID");
            _RowID = StructuralObject.SetValidValue(value);
            ReportPropertyChanged("RowID");
            OnRowIDChanged();
        }
    }
    private global::System.Int16 _RowID;
    partial void OnRowIDChanging(global::System.Int16 value);
    partial void OnRowIDChanged();

    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
    [DataMemberAttribute()]
    public global::System.String NickName
    {
        get
        {
            return _NickName;
        }
        set
        {
            OnNickNameChanging(value);
            ReportPropertyChanging("NickName");
            _NickName = StructuralObject.SetValidValue(value, false);
            ReportPropertyChanged("NickName");
            OnNickNameChanged();
        }
    }
    private global::System.String _NickName;
    partial void OnNickNameChanging(global::System.String value);
    partial void OnNickNameChanged();
    .
    .
    .

無需遍歷結果並將輸出參數添加到LoggedInMember對象,如何動態映射這些參數,以便通過WCF服務返回它們的列表?

如果我嘗試var results = connection.Query<LoggedInMember>("sq_mobile_get_buddies_v35", ...我收到以下錯誤:

System.Data.DataException:解析列0時出錯(RowID = 1 - Int64)---> System.InvalidCastException:指定的強制轉換無效。在反序列化......

一般承認的答案

解決方法是使用EF創建一個從sproc派生的複雜對象:

    public ProfileDetailsByID_Result GetAllProfileDetailsByID(int profileID)
    {
        using (IDbConnection connection = OpenConnection("PrimaryDBConnectionString"))
        {
            try
            {
                var profile = connection.Query<ProfileDetailsByID_Result>("sproc_profile_get_by_id",
                    new { profileid = profileID },
                    commandType: CommandType.StoredProcedure).FirstOrDefault();

                return profile;
            }
            catch (Exception ex)
            {
                ErrorLogging.Instance.Fatal(ex);        // use singleton for logging
                return null;
            }
        }
    }

在這種情況下,ProfileDetailsByID_Result是我通過複雜類型創建過程使用Entity Framework手動創建的對象(右鍵單擊模型圖,選擇Add / Complex Type ...,或使用RHS上的Complex Types樹)。

一個小心的詞

因為此對象的屬性是從sproc派生的,所以EF無法知道屬性是否可為空。對於任何可空屬性類型, 必須通過選擇屬性並將其Nullable屬性設置為true手動配置它們


熱門答案

猜測你的SQL列是一個bigint (即Int64又名long )但你的.Net類型有一個Int16屬性。

你可以玩轉換並忽略存儲過程,例如:

var results = connection.Query<LoggedInMember>("select cast(9 as smallint) [RowID] ...");

您只需選擇要返回對象的屬性和類型。 ( smallintInt16的SQL等價物)



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因