Reputation: 151
So I most likely have something wrong, I know this already. I am just unable to figure out what exactly is wrong. I have tried this two different ways and I get different results from each way. Well here goes, I am trying to use Stored Procedures to get data for the view. I have two View Models that are as such:
public class CharacterCraftNamesListViewModel
{
public string CharFullName { get; set; }
public string ProfName { get; set; }
}
and
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; }
}
I also have the two corresponding Stored Procedures in the database.
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
and
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]
Inside my controller I have the following:
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);
}
When I look at the debugger I see the following:
So with this I just end up getting a blank page.
Now I have tried placing the stored procedures in the controller itself, and have ended up with a different output in the debugger.
Inside the controller I tried:
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);
}
This gives me the following in the debugger:
While the data in the alist is definitely wrong the count for it is correct. The names displays the correct ProfName but the incorrect data on the CharFullName. So I am lost with what to do here. If I execute the stored procedures in T-SQL I get the correct data displayed, but that is on the server alone. I have been unable to make MVC and SQL play correctly, and I know it is my code. I just cannot see what is wrong with the code. Any thoughts to where I went wrong?
Upvotes: 0
Views: 1125
Reputation: 151
Ok, I have figured this out. There were two things wrong that were causing the issue. With the following code, the program was not calling it to the SQL Server correctly:
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();
While the SQLQuery call is correct through everything I have read, when I placed into SSMS what was outputted by the program, I got null sets. So I changed the sql: "GetCharacterNameProfessionName" and sql: "GetCharacterCraftRank" to sql: "GetCharacterNameProfessionName @p0" and sql: "GetCharacterCraftRank @p0, @p1". This then game me an output similar to when I wrote the queries out in the controller.
The next issue came down to naming convention. I was really baffled when I did a Database First Model to see what would happen, and it actually worked. But I realized as I was doing that I was able to map the names of my stored procedure columns to columns I had in the code. That is when it dawned on me, as simple change to my stored procedures, to have the column names match what I was putting in the program and everything worked correctly. A few minor tweaks and now my get controller looks like this:
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);
}
I hope that this helps someone else.
Upvotes: 0