【问题标题】:ASP.NET MVC and Stored Procedures not working correctlyASP.NET MVC 和存储过程无法正常工作
【发布时间】:2017-01-01 18:03:39
【问题描述】:

所以我很可能有什么问题,我已经知道了。我只是无法弄清楚到底出了什么问题。我已经尝试了这两种不同的方法,并且每种方法都得到了不同的结果。 好了,我正在尝试使用存储过程来获取视图的数据。我有两个这样的视图模型:

public class CharacterCraftNamesListViewModel
    {
        public string CharFullName { get; set; }
        public string ProfName { get; set; }
    }

public class CharacterCraftCraftListViewModel
    {
        public string CraftClassName { get; set; }
        public int CharCraftCharID { get; set; }
        public int CharCraftClassID { get; set; }
        public int CharCraftLevelID { get; set; }
        public bool CraftLevelSet { get; set; }
        public string CraftLevelName { get; set; }
        public bool CraftLevelMastery { get; set; }

    }

我在数据库中也有两个对应的存储过程。

CREATE PROCEDURE [dbo].[GetCharacterCraftCharacterNameProfessionName]
                @CharID int = NULL
    AS
    WITH CHCRNames_CTE ( [CCCID], [CharFull], [ProfName] )
    AS
        (SELECT 
            Character_Char_ID,
            CASE 
                    WHEN b.Char_Last_Name IS NULL THEN b.Char_First_Name
                    ELSE b.Char_First_Name + '  ' + b.Char_Last_Name
            END AS FullName,
            c.Profession_Name
            FROM CharacterCraft a LEFT OUTER JOIN
            [Character] b ON a.Character_Char_ID = b.Char_ID LEFT OUTER JOIN
            [Profession] c ON c.Profession_ID = b.Profession_Profession_ID
            )
    SELECT DISTINCT CharFull, ProfName
    FROM CHCRNames_CTE
    WHERE CCCID = @CharID

CREATE PROCEDURE [dbo].[GetCharacterCraftRank]
                @CharID int = NULL,
                @Rank int = NULL
    AS  
    WITH CHCR_CTE ( [Rank], [CCID], [CCCCID], [CCName], [CLCLID], [CLName], [CLTier], [CLS], [CLM])
    AS
        (SELECT
                DENSE_RANK() OVER(PARTITION BY(a.Character_Char_ID)ORDER BY (a.CraftClass_Craft_Class_ID)) AS [Rank],
                a.Character_Char_ID,
                CraftClass_Craft_Class_ID,
                c.Craft_Class_Name,
                CraftLevel_Craft_Level_ID,
                d.Craft_Level_Name,
                d.Craft_Level_Tier,
                Craft_Level_Set,
                Craft_Level_Mastery
        FROM CharacterCraft a LEFT OUTER JOIN
        [Character] b ON a.Character_Char_ID = b.Char_ID LEFT OUTER JOIN
        [CraftClass] c ON a.CraftClass_Craft_Class_ID = c.Craft_Class_ID LEFT OUTER JOIN
        [CraftLevel] d ON a.CraftLevel_Craft_Level_ID = d.Craft_Level_ID
        )
    SELECT  [CCID], [CCCCID], [CCName], [CLCLID], [CLS], [CLName], [CLM] 
    FROM CHCR_CTE 
    WHERE [CCID]= @CharID AND [Rank] = @Rank
    ORDER BY [Rank], [CLTier]

在我的控制器中,我有以下内容:

public async Task<ActionResult> Edit(int? id)
            {
                if (id == null)
                {
                    return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
                } 
    var names = await db.Database.SqlQuery<CharacterCraftNamesListViewModel>( sql: "GetCharacterCraftCharacterNameProfessionName", parameters: new object[] { id } ).ToListAsync();
            var alist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( sql: "GetCharacterCraftRank", parameters: new object[] { id, 1 } ).ToListAsync();
            var blist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( sql: "GetCharacterCraftRank", parameters: new object[] { id, 2 }  ).ToListAsync();
            var clist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( sql: "GetCharacterCraftRank", parameters: new object[] { id, 3 }  ).ToListAsync();
            var characterCraft = new CharacterCraftViewModel()
            {
                CharNames = names.AsEnumerable(),
                CraftListA = alist.AsEnumerable(),
                CraftListB = blist.AsEnumerable(),
                CraftListC = clist.AsEnumerable()
            };
    if (characterCraft == null)
        {
            return HttpNotFound();
        }
        return View(characterCraft);
    }

当我查看调试器时,我看到以下内容:

  • id 1
  • 姓名数=0
  • alist Count=0
  • 列表计数=0
  • 列表计数=0
  • 角色工艺
    {LotroMvc.Models.CharacterCraftViewModels.CharacterCraftViewModel}

所以我最终得到了一个空白页。

现在我尝试将存储过程放置在控制器本身中,并在调试器中得到不同的输出。

在我尝试过的控制器内部:

public async Task<ActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
var query = "WITH CHCRNames_CTE( [CCCID], [CharFull], [ProfName] ) "
                    + "AS "
                    + "( SELECT "
                    + "Character_Char_ID, "
                    + "CASE "
                    + "WHEN b.Char_Last_Name IS NULL THEN b.Char_First_Name "
                    + "ELSE b.Char_First_Name + '  ' + b.Char_Last_Name "
                    + "END AS FullName, "
                    + "c.Profession_Name "
                    + "FROM CharacterCraft a LEFT OUTER JOIN "
                    + "dbo.[Character] b ON a.Character_Char_ID = b.Char_ID LEFT OUTER JOIN "
                    + "dbo.[Profession] c ON c.Profession_ID = b.Profession_Profession_ID "
                    + ") "
                    + "SELECT DISTINCT CharFull, ProfName "
                    + "FROM CHCRNames_CTE "
                    + "WHERE CCCID = @p0";
        var names = await db.Database.SqlQuery<CharacterCraftNamesListViewModel>( query, id ).ToListAsync();
        var rank = "WITH CHCR_CTE( [Rank], [CCID], [CCCCID], [CCName], [CLCLID], [CLName], [CLTier], [CLS], [CLM] )"
                    + "AS "
                    + "( SELECT "
                    + "DENSE_RANK() OVER(PARTITION BY(a.Character_Char_ID)ORDER BY (a.CraftClass_Craft_Class_ID)) AS [Rank], "
                    + "a.Character_Char_ID, "
                    + "CraftClass_Craft_Class_ID, "
                    + "c.Craft_Class_Name, "
                    + "CraftLevel_Craft_Level_ID, "
                    + "d.Craft_Level_Name, "
                    + "d.Craft_Level_Tier, "
                    + "Craft_Level_Set, "
                    + "Craft_Level_Mastery "
                    + "FROM CharacterCraft a LEFT OUTER JOIN "
                    + "[Character] b ON a.Character_Char_ID = b.Char_ID LEFT OUTER JOIN "
                    + "[CraftClass] c ON a.CraftClass_Craft_Class_ID = c.Craft_Class_ID LEFT OUTER JOIN "
                    + "[CraftLevel] d ON a.CraftLevel_Craft_Level_ID = d.Craft_Level_ID "
                    + ") "
                    + "SELECT  [CCID], [CCCCID], [CCName], [CLCLID], [CLS], [CLName], [CLM] "
                    + "FROM CHCR_CTE "
                    + "WHERE [CCID]= @p0 AND [Rank] = @p1 "
                    + "ORDER BY [Rank], [CLTier]";
        var alist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( rank, parameters: new object[] { id, 1 } ).ToListAsync();
        var blist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( rank, parameters: new object[] { id, 2 }  ).ToListAsync();
        var clist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( rank, parameters: new object[] { id, 3 }  ).ToListAsync();
        var characterCraft = new CharacterCraftViewModel()
        {
            CharNames = names.AsEnumerable(),
            CraftListA = alist.AsEnumerable(),
            CraftListB = blist.AsEnumerable(),
            CraftListC = clist.AsEnumerable()
        };
if (characterCraft == null)
    {
        return HttpNotFound();
    }
    return View(characterCraft);
}

这在调试器中为我提供了以下信息:

  • 这个 {LotroMvc.Controllers.CharacterCraftsController}
  • id 1
  • 查询“与 CHCRNames_CTE([CCCID], [CharFull], [ProfName]) AS ( 选择 Character_Char_ID,当 b.Char_Last_Name 为 NULL THEN 时的情况
    b.Char_First_Name ELSE b.Char_First_Name + ' ' + b.Char_Last_Name
    END AS FullName, c.Profession_Name FROM CharacterCraft a LEFT OUTER
    加入 dbo.[Character] b ON a.Character_Char_ID = b.Char_ID LEFT OUTER 加入 dbo.[职业] c ON c.Profession_ID =
    b.Profession_Profession_ID ) SELECT DISTINCT CharFull, ProfName FROM CHCRNames_CTE WHERE CCCID = @p0" 名称计数 = 1
  • [0] {LotroMvc.Models.CharacterCraftViewModels.CharacterCraftNamesListViewModel}
  • CharFullName 为空
  • ProfName "Historian"
  • rank "WITH CHCR_CTE([Rank], [CCID]、[CCCCID]、[CCName]、[CLCLID]、[CLName]、[CLTier]、[CLS]、 [CLM] )AS ( SELECT DENSE_RANK() OVER(PARTITION BY(a.Character_Char_ID)ORDER BY (a.CraftClass_Craft_Class_ID)) AS [等级],a.Character_Char_ID,CraftClass_Craft_Class_ID, c.Craft_Class_Name、CraftLevel_Craft_Level_ID、d.Craft_Level_Name、 d.Craft_Level_Tier、Craft_Level_Set、Craft_Level_Mastery FROM CharacterCraft a LEFT OUTER JOIN [Character] b ON a.Character_Char_ID = b.Char_ID 左外连接 [CraftClass] c ON a.CraftClass_Craft_Class_ID = c.Craft_Class_ID 左外连接 [CraftLevel] d ON a.CraftLevel_Craft_Level_ID = d.Craft_Level_ID ) 选择 [CCID]、[CCCCID]、[CCName]、[CLCLID]、[CLS]、[CLName]、 [CLM] 来自 CHCR_CTE,其中 [CCID]= @p0 AND [Rank] = @p1 ORDER BY [等级]、[CLTier]”
  • alist 计数 = 9
  • [0] {LotroMvc.Models.CharacterCraftViewModels.CharacterCraftCraftListViewModel}
  • CharCraftCharID 0
  • CharCraftClassID 0
  • CharCraftLevelID 0
  • CraftClassName 为空
  • CraftLevelMastery 错误
  • CraftLevelName 为空
  • CraftLevelSet 错误
  • (等等)

虽然 alist 中的数据肯定是错误的,但它的计数是正确的。名称显示正确的 ProfName 但 CharFullName 上的数据不正确。所以我不知道在这里做什么。如果我在 T-SQL 中执行存储过程,我会显示正确的数据,但这仅在服务器上。我一直无法让 MVC 和 SQL 正确播放,我知道这是我的代码。我只是看不出代码有什么问题。有没有想过我哪里出错了?

【问题讨论】:

    标签: c# asp.net sql-server stored-procedures


    【解决方案1】:

    好的,我想通了。有两件事错误导致了这个问题。使用以下代码,程序没有正确调用 SQL Server:

    var names = await db.Database.SqlQuery<CharacterCraftNamesListViewModel>( sql: "GetCharacterCraftCharacterNameProfessionName", parameters: new object[] { id } ).ToListAsync();
            var alist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( sql: "GetCharacterCraftRank", parameters: new object[] { id, 1 } ).ToListAsync();
            var blist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( sql: "GetCharacterCraftRank", parameters: new object[] { id, 2 }  ).ToListAsync();
            var clist = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>( sql: "GetCharacterCraftRank", parameters: new object[] { id, 3 }  ).ToListAsync();
    

    虽然 SQLQuery 调用在我阅读的所有内容中都是正确的,但当我将程序输出的内容放入 SSMS 时,我得到了空集。所以我将sql:“GetCharacterNameProfessionName”和sql:“GetCharacterCraftRank”更改为sql:“GetCharacterNameProfessionName @p0”和sql:“GetCharacterCraftRank @p0,@p1”。然后,这会向我输出类似于我在控制器中写出查询时的输出。

    下一个问题归结为命名约定。当我做一个数据库优先模型来看看会发生什么时,我真的很困惑,而且它确实有效。但我意识到,当我这样做时,我能够将存储过程列的名称映射到代码中的列。那时我突然意识到,作为对我的存储过程的简单更改,让列名与我在程序中放入的内容相匹配,并且一切正常。一些小的调整,现在我的 get 控制器看起来像这样:

    public async Task<ActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            var characterCraft = new CharacterCraftViewModel()
            {
                CharNames = await db.Database.SqlQuery<CharacterCraftNamesListViewModel>(sql: "GetCharacterCraftCharacterNameProfessionName @p0", parameters: new object[] { id }).FirstAsync(),
                CraftListA = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>(sql: "GetCharacterCraftRank @p0, @p1", parameters: new object[] { id, 1 }).ToListAsync(),
                CraftListB = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>(sql: "GetCharacterCraftRank @p0, @p1", parameters: new object[] { id, 2 }).ToListAsync(),
                CraftListC = await db.Database.SqlQuery<CharacterCraftCraftListViewModel>(sql: "GetCharacterCraftRank @p0, @p1", parameters: new object[] { id, 3 }).ToListAsync()
            };
    
            if (characterCraft == null)
            {
                return HttpNotFound();
            }
            return View(characterCraft);
        }
    

    我希望这对其他人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-27
      相关资源
      最近更新 更多