Entity query select top1 - c#

i having problem in sql by using ExecuteStoreQuery Please see the example at below
My coding
private void ChildMenuItem()
{
using (LEWREDBEntities ctx = new LEWREDBEntities())
{
string result = #"
WITH ctLevel
AS
(
SELECT
C_TASK_ID AS Child
,P_Task_ID AS Parent
,common_task. TASK_SEQ AS taskSeq
,1 AS [Level]
,CAST( TASK_SEQ AS VARCHAR(MAX)) AS [taskOrder]
,CAST (Replicate('', 1) + common_task.TASK_NAME AS VARCHAR(MAX)) AS [Task_Name]
FROM
[COMMON.TASK_REL] as common_task_rel,
[COMMON.TASK] as common_task
WHERE
common_task_rel.C_TASK_ID = common_task.TASK_ID
and common_task.[TASK_TYPE] = 'F' AND common_task.[MODULE_CODE] = 'PRODE' AND common_task.[STATUS] <> 'D'
and C_TASK_ID =357
UNION ALL
SELECT
C_TASK_ID AS Child
,P_Task_ID AS Parent
,common_task. TASK_SEQ AS taskSeq
,[Level] + 1 AS [Level]
,[taskOrder] + '.' + CAST(TASK_SEQ AS VARCHAR(MAX)) AS [taskOrder]
,CAST (Replicate('', [Level] + 1) + common_task.TASK_NAME AS VARCHAR(MAX)) AS [Task_Name]
FROM
[COMMON.TASK_REL]as common_task_rel
INNER JOIN
ctLevel
ON
( P_Task_ID = Child ) ,
[COMMON.TASK] as common_task
WHERE
common_task_rel.C_TASK_ID = common_task.TASK_ID
and common_task.[TASK_TYPE] = 'F' AND common_task.[MODULE_CODE] = 'PRODE' AND common_task.[STATUS] <> 'D'
)
SELECT
common_task.Task_Name,
common_task_url.TASK_URL,
ctLevel.CHILD
FROM
ctLevel,
[COMMON.ACL] as common_acl,
[COMMON.STAFF_ROLE] as common_staff_role,
[COMMON.TASK_URL] as common_task_url,
[COMMON.TASK] as common_task,
[COMMON.STAFF_MODULE] as common_staff_module,
[common.module] as common_module
where ctLevel.Level =3
and ctLevel.Child = common_acl.TASK_ID
and common_acl.READ_ACCESS ='Y'
and common_acl.STATUS <>'D'
and common_acl.ROLE_ID = common_staff_role.ROLE_ID
and common_staff_role.STATUS <>'D'
and common_staff_role.STAFF_ID ='user'
and common_staff_role.STAFF_ID = common_staff_module.STAFF_ID
and common_staff_module.MODULE_CODE =common_module.MODULE_CODE
and common_staff_module.STATUS<>'D'
and common_staff_module.MODULE_CODE = common_module.MODULE_CODE
and common_module.STATUS <>'D' and common_module.MODULE_CODE ='PRODE'
and common_acl.TASK_ID = common_task.TASK_ID
and common_task.STATUS <>'D'
and common_task.TASK_TYPE ='F'
and common_task.TASK_POSITION ='S'
and common_task.TASK_ID = common_task_url.TASK_ID
and common_task_url.DEFAULT_URL ='Y'
and common_task_url.STATUS<>'D'
Group By
[taskOrder],common_task.Task_Name, TASK_URL,ctLevel.CHILD
order by [taskOrder],common_task.Task_Name, TASK_URL,ctLevel.CHILD";
var query = ctx.ExecuteStoreQuery<dlcGvTask>
(result);
foreach (dlcGvTask gvTask in query.ToList())
{
MenuItem navigation = new MenuItem(gvTask.TASK_NAME, gvTask.Child.ToString(), "","");
MenuChild.Items.Add(navigation);
}
//Here????
var id = (from table in query
select table.Child).Take(1);
;
}
}
Now i got a question.How can i select the top 1 of the Record?

In your code
//Here????
var id = (from table in query
select table.Child).Take(1);
Try
var id = query.First();
//Or
var id = query.Take(1);

Try to do something like this:-
Select Top 1 ..... ;
OR
..... Where ROW_NUMBER() = 1;

Related

ASP.NET MVC and Stored Procedures not working correctly

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:
id 1
names Count=0
alist Count=0
blist Count=0
clist Count=0
characterCraft
{LotroMvc.Models.CharacterCraftViewModels.CharacterCraftViewModel}
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:
this {LotroMvc.Controllers.CharacterCraftsController}
id 1
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" names Count = 1
[0] {LotroMvc.Models.CharacterCraftViewModels.CharacterCraftNamesListViewModel}
CharFullName null
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
[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]"
alist Count = 9
[0] {LotroMvc.Models.CharacterCraftViewModels.CharacterCraftCraftListViewModel}
CharCraftCharID 0
CharCraftClassID 0
CharCraftLevelID 0
CraftClassName null
CraftLevelMastery false
CraftLevelName null
CraftLevelSet false
(and so forth)
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?
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.

How can I filter fields by current logged user into stored procedure

I have an stored procedure where I get two different values, one is real one and the other is goal value
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[IndicatorTrainingGaugeMonth]
AS
SET FMTONLY OFF
BEGIN
SET NOCOUNT ON;
SELECT
' ' AS MonthName,
gd.Month,
ISNULL(SUM(gd.Meta), 0) AS Total
INTO
#Meta
FROM
[dbo].[Goal] g (NOLOCK)
INNER JOIN
[dbo].[GoalDetail] gd (NOLOCK) ON g.Id = gd.IdGoal
INNER JOIN
[dbo].[GoalClassification] gc (NOLOCK) ON gd.IdClassification = gc.Id
WHERE
gc.Id IN (2, 7)
AND g.Year = YEAR(GETDATE())
AND gd.Month = MONTH(GETDATE())
GROUP BY
gd.Month
SELECT
' ' AS MonthName,
MONTH(t.InitDate) AS Month,
ISNULL(SUM(te.Hours), 0) AS Total
INTO
#REAL
FROM
[dbo].[Training] t (NOLOCK)
INNER JOIN
[dbo].[TrainingEmployee] te (NOLOCK) ON t.Id = te.IdTraining
WHERE
YEAR(t.InitDate) = YEAR (GETDATE())
AND MONTH(t.InitDate) = MONTH(GETDATE())
GROUP BY
t.InitDate
SELECT
--m.MonthName
m.Month,
ISNULL(m.Total, 0) AS Meta,
ISNULL(r.Total, 0) AS Real,
--COS ((ISNULL(r.Total,0) - 0) / (ISNULL(m.Total,0) - 0) * PI() )AS Value
FROM
#Meta m
LEFT JOIN
#Real ON m.Month = r.Month
DROP TABLE #Meta
DROP TABLE #Real
END
There I get two values for example: Real: 20 Meta(Goal): 100
But now I want to filter these result by UserBranch. In my table AspNetUsers I have a foreign key of BranchOfficeId, so every user has a Branch
How can I take currentUserLogged and filter by his branch? Regards
---Update---
I get currently logged user in controller like:
public ActionResult IndicatorTrainingGauge()
{
string result = string.Empty;
var userId = User.Identity.GetUserId();
var branchOfficeId = UserClass.GetUserBranchOfficeId(userId);
try
{
result = new JavaScriptSerializer().Serialize(Dashboard.IndicatorTrainingGauge(branchOfficeId));
}
catch (Exception)
{
throw;
}
return Content(result, "application/json");
}
And I catch in a class:
public static object IndicatorTrainingGauge(int branchOfficeId)
{
try
{
using (var context = new EF.SA())
{
var month = context.IndicatorTrainingGaugeMonth().FirstOrDefault();
var year = context.IndicatorTrainingGaugeYear().FirstOrDefault();
return new { month, year };
}
}
catch (Exception)
{
throw;
}
}
Note: IndicatorTrainingGaugeMonth is a stored procedure.
So now what I need modified to filter my store by branch? Regards

LINQ Left join Query

I am trying converting sql query into LINQ but after write query unable to fetch record from resultset
SELECT T.ServiceOrderNo,T.STATUS, T.SubStatus,T.orderVersion,T.OrderDate
,#pid, T.EventID, 'FOI'
FROM #temp1 T
LEFT JOIN Tbl_Service_Order_Progress O ON T.ServiceOrderNo DATABASE_DEFAULT = O.ServiceOrderNo
AND O.PARENTID = #pid
AND O.ServiceOrderType = 'FOI'
WHERE O.ServiceOrderNo IS NULL
Above Query following I'm trying in LINQ
var lstInsertFOI = (from i in lstFOI
join j in lstSOP on i.fulfilmentOrderItemIdentifier equals j.ServiceOrderNo into res
from subRight in res.DefaultIfEmpty()
where subRight.ParentId == parentId && subRight.ServiceOrderNo == null && subRight.ServiceOrderType.Equals("FOI")
select new
{
ServiceOrderNo = subRight.ServiceOrderNo == null ? i.fulfilmentOrderItemIdentifier : subRight.ServiceOrderNo,
EventStatus = i.status,
EventSubStatus = i.subStatus,
OrderVersion = i.orderVersion,
EVENTRECEIVEDDATE = i.orderDate,
ParentId = parentId,
EventID = i.eventID,
ServiceOrderType = "FOI",
}).ToList();
above linq query does not fetch expected result, which should return number of records from lstFOI list, but returns no record. Is the linq query correct?
Let start with SQL query.
LEFT JOIN Tbl_Service_Order_Progress O
ON T.ServiceOrderNo = O.ServiceOrderNo
AND O.PARENTID = #pid AND O.ServiceOrderType = 'FOI'
is equivalent to
LEFT JOIN (SELECT * FROM Tbl_Service_Order_Progress
WHERE PARENTID = #pid AND ServiceOrderType = 'FOI') O
ON T.ServiceOrderNo = O.ServiceOrderNo
then
WHERE O.ServiceOrderNo IS NULL
means that the query is actually using anti-join, i.e. include all the records from the left side that do not have a matching records from the right side.
With all that in mind, the equivalent LINQ query should be like this:
var lstInsertFOI = (
from i in lstFOI
join j in lstSOP
.Where(e => e.ParentId == parentId && subRight.ServiceOrderType == "FOI")
on i.fulfilmentOrderItemIdentifier equals j.ServiceOrderNo into res
where !res.Any()
select new
{
ServiceOrderNo = i.fulfilmentOrderItemIdentifier,
EventStatus = i.status,
EventSubStatus = i.subStatus,
OrderVersion = i.orderVersion,
EVENTRECEIVEDDATE = i.orderDate,
ParentId = parentId,
EventID = i.eventID,
ServiceOrderType = "FOI",
}).ToList();

Linq Left join query in c#

Doing some stuff linq left join query but facing some problem. Not able to get proper result following sql query need to convert into linq
INSERT INTO tbl_service_order_attributes_versioning(ServiceOrderNo, AttributeId, AttributeValue, parentid, AttributeType, Dt_Stamp, VERSION)
SELECT
T.ServiceOrderNo, T.COIID, T.COI_Identifier,
#pid, 'MBM', getDate(), #ORDERVERSION
FROM
#temp1 T
LEFT JOIN
tbl_service_order_attributes_versioning O WITH(NOLOCK)
ON T.ServiceOrderNo = O.ServiceOrderNo COLLATE database_default
AND T.COIID = O.AttributeID
AND O.PARENTID = #pid
WHERE
O.ServiceOrderNo IS NULL
I have converted this query into a Linq query:
var soiAttr = (from s in ctxParser.TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING
where s.ParentId == parentId
select s).ToList();
var resultJoinCOI = (from soaI in soiAttr
join iFoi in listFOI on soaI.ServiceOrderNo equals iFoi.fulfilmentOrderItemIdentifier
where iFoi.coiId == soaI.AttributeId &&
iFoi.parentId == parentId &&
soaI.ServiceOrderNo == null
select iFoi).ToList();
if (resultJoinCOI.Count > 0)
{
var listToInsert = (from item in resultJoinCOI
select new TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING
{
ServiceOrderNo = item.fulfilmentOrderItemIdentifier,
AttributeId = item.coiId,
AttributeValue = item.coiIdentifier,
ParentId = parentId,
AttributeType = "MBM",
DT_Stamp = DateTime.Now,
VERSION = orderVersion
});
ctxParser.TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING.AddRange(listToInsert);
ctxParser.SaveChanges();
}
The code is executed but result are not correct.
You need to use DefaultIfEmpty (https://msdn.microsoft.com/en-us/library/bb360179.aspx). Here's a reading from MSDN: https://msdn.microsoft.com/en-us/library/bb397895.aspx
In your case it would be something like:
var resultJoinCOI = (
from iFoi in listFOI
join soaI in soiAttr on iFoi.fulfilmentOrderItemIdentifier equals soaI.ServiceOrderNo into res
from subIFoi in res.DefaultIfEmpty()
where iFoi.coiId == soaI.AttributeId && iFoi.parentId == parentId && subIFoi == null
select iFoi).ToList();
Following code that execute successfully. and getting right result.
var soiAttr = (from s in ctxParser.TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING
where s.ParentId == parentId
select s).ToList();
var resultJoinCOI = (from iFoi in listFOI
join soaI in soiAttr on
new
{
ServiceOrderNo = iFoi.fulfilmentOrderItemIdentifier,
AttributeId = iFoi.coiId
}
equals new
{
ServiceOrderNo = soaI.ServiceOrderNo,
AttributeId = soaI.AttributeId
}
into res
from subFoi in res.DefaultIfEmpty()
select new
{
fulfilmentOrderItemIdentifier = iFoi.fulfilmentOrderItemIdentifier,
coiId = iFoi.coiId,
coiIdentifier = iFoi.coiIdentifier,
AttributeId = subFoi == null ? 0 : subFoi.AttributeId,
ParentId = subFoi == null ? parentId : subFoi.ParentId,
ServiceOrderNo = subFoi == null ? string.Empty: subFoi.ServiceOrderNo
});
if (resultJoinCOI != null)
{
if (resultJoinCOI.Count() > 0)
{
var listToInsert = (from item in resultJoinCOI
select new TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING
{
ServiceOrderNo = item.fulfilmentOrderItemIdentifier,
AttributeId = item.coiId,
AttributeValue = item.coiIdentifier,
ParentId = parentId,
AttributeType = "MBM",
DT_Stamp = DateTime.Now,
VERSION = orderVersion
});
ctxParser.TBL_SERVICE_ORDER_ATTRIBUTES_VERSIONING.AddRange(listToInsert);
ctxParser.SaveChanges();
}
}
In this way we can implement left join in linq. as per above SQL Query(see above sql statement).

Linq To Sql Concat() dropping fields in created TSQL

This is strange.
I am moving a stored proc to a service. The TSQL unions multiple selects. To replicate this I created multiple queries resulting in a common new concrete type. Then I issue a return result.ToString(); and the resulting SQL selects have varying numbers of columns specified thus causing an MSSQL Msg 205...
using (var db = GetDb())
{
var fundInv = from f in db.funds
select
new Investments
{
Company = f.company,
FullName = f.fullname,
Admin = f.admin,
Fund = f.fund1,
FundCode = f.fundcode,
Source = STR_FUNDS,
IsPortfolio = false,
IsActive = f.active,
Strategy = f.strategy,
SubStrategy = f.substrategy,
AltStrategy = f.altstrategy,
AltSubStrategy = f.altsubstrategy,
Region = f.region,
AltRegion = f.altregion,
UseAlternate = f.usealt,
ClassesAllowed = f.classallowed
};
var stocksInv = from s in db.stocks
where !fundInv.Select(f => f.Company).Contains(s.vehcode) select
new Investments
{
Company = s.company,
FullName = s.issuer,
Admin = STR_PRS,
Fund = s.shortname,
FundCode = s.vehcode,
Source = STR_STOCK,
IsPortfolio = false,
IsActive = (s.inactive == null),
Strategy = s.style,
SubStrategy = s.substyle,
AltStrategy = s.altstyle,
AltSubStrategy = s.altsubsty,
Region = s.geography,
AltRegion = s.altgeo,
UseAlternate = s.usealt,
ClassesAllowed = STR_GENERIC
};
var bondsInv = from oi in db.bonds
where !fundInv.Select(f => f.Company).Contains(oi.vehcode)
select
new Investments
{
Company = string.Empty,
FullName = oi.issue,
Admin = STR_PRS1,
Fund = oi.issue,
FundCode = oi.vehcode,
Source = STR_BONDS,
IsPortfolio = false,
IsActive = oi.closed,
Strategy = STR_OTH,
SubStrategy = STR_OTH,
AltStrategy = STR_OTH,
AltSubStrategy = STR_OTH,
Region = STR_OTH,
AltRegion = STR_OTH,
UseAlternate = false,
ClassesAllowed = STR_GENERIC
};
return (fundInv.Concat(stocksInv).Concat(bondsInv)).ToList();
}
The code above results in a complex select statement where each "table" above has different column count. (see SQL below) I've been trying a few things but no change yet. Ideas are welcome.
SELECT [t6].[company] AS [Company],
[t6].[fullname] AS [FullName],
[t6].[admin] AS [Admin],
[t6].[fund] AS [Fund],
[t6].[fundcode] AS [FundCode],
[t6].[value] AS [Source],
[t6].[value2] AS [IsPortfolio],
[t6].[active] AS [IsActive],
[t6].[strategy] AS [Strategy],
[t6].[substrategy] AS [SubStrategy],
[t6].[altstrategy] AS [AltStrategy],
[t6].[altsubstrategy] AS [AltSubStrategy],
[t6].[region] AS [Region],
[t6].[altregion] AS [AltRegion],
[t6].[usealt] AS [UseAlternate],
[t6].[classallowed] AS [ClassesAllowed]
FROM (
SELECT [t3].[company],
[t3].[fullname],
[t3].[admin],
[t3].[fund],
[t3].[fundcode],
[t3].[value],
[t3].[value2],
[t3].[active],
[t3].[strategy],
[t3].[substrategy],
[t3].[altstrategy],
[t3].[altsubstrategy],
[t3].[region],
[t3].[altregion],
[t3].[usealt],
[t3].[classallowed]
FROM (
SELECT [t0].[company],
[t0].[fullname],
[t0].[admin],
[t0].[fund],
[t0].[fundcode],
#p0 AS [value],
[t0].[active],
[t0].[strategy],
[t0].[substrategy],
[t0].[altstrategy],
[t0].[altsubstrategy],
[t0].[region],
[t0].[altregion],
[t0].[usealt],
[t0].[classallowed]
FROM [zInvest].[funds] AS [t0]
UNION ALL
SELECT [t1].[company],
[t1].[issuer],
#p6 AS [value],
[t1].[shortname],
[t1].[vehcode],
#p7 AS [value2],
#p8 AS [value3],
(CASE
WHEN [t1].[inactive] IS NULL THEN 1
ELSE 0
END) AS [value5],
[t1].[style],
[t1].[substyle],
[t1].[altstyle],
[t1].[altsubsty],
[t1].[geography],
[t1].[altgeo],
[t1].[usealt],
#p10 AS [value6]
FROM [zBank].[stocks] AS [t1]
WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [zInvest].[funds] AS [t2]
WHERE [t2].[company] = [t1].[vehcode]
))) AND ([t1].[vehcode] <> #p2) AND (SUBSTRING([t1].[vehcode], #p3 + 1, #p4) <> #p5)
) AS [t3]
UNION ALL
SELECT #p11 AS [value],
[t4].[issue],
#p12 AS [value2],
[t4].[vehcode],
#p13 AS [value3],
#p14 AS [value4],
[t4].[closed],
#p16 AS [value6],
#p17 AS [value7]
FROM [zMut].[bonds] AS [t4]
WHERE NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM [zInvest].[funds] AS [t5]
WHERE [t5].[company] = [t4].[vehcode]
))
) AS [t6]
Think it is a bug in LINQ to SQL. You can find it here:
http://connect.microsoft.com/VisualStudio/feedback/details/355734/linq-to-sql-produces-incorrect-tsql-when-using-union-or-concat
Hope the workaround given there works for you.

Categories

Resources