I am getting the error:
The specified LINQ expression contains references to queries that are associated with different contexts.
because I'm trying to combine two different DbContexts, each from separate databases.
I was trying to convert this SQL:
SELECT orderformdump.itemno,basedescription,info,upc,CAST(UNITPRICE AS DECIMAL(18,2)),caseqty, sum(qty) AS userquantity
FROM [DataWarehouse].[dbo].[ORDERFORMDUMP]
LEFT JOIN PPPLTD.dbo.ICPRICP ON replace([DataWarehouse].[dbo].[ORDERFORMDUMP].[ITEMNO],'-','') = ICPRICP.ITEMNO
LEFT JOIN PPPLTD.dbo.WEBITEMINFO ON ORDERFORMDUMP.ITEMNO = WEBITEMINFO.ITEMNO
LEFT JOIN pppltd.dbo.weboeordh ON [user] = #username
LEFT JOIN pppltd.dbo.weboeordd ON pppltd.dbo.WEBOEORDD.ITEMNO = REPLACE(datawarehouse.dbo.ORDERFORMDUMP.ITEMNO,'-','') and weboeordd.ORDUNIQ = weboeordh.orduniq
Left JOIN pppltd.dbo.weboeordsubmit ON weboeordsubmit.orduniq = weboeordd.ORDUNIQ and weboeordd.ORDUNIQ != weboeordsubmit.orduniq
LEFT JOIN PPPLTD.dbo.WEBLOGINACCESS ON WEBLOGINACCESS.[USER] = #username
LEFT JOIN PPPLTD.dbo.ARCUS ON ARCUS.IDCUST = WEBLOGINACCESS.CUSTID
where (allowinbc = 'Yes' or allowinab = 'Yes')
AND [PRICELIST] = ARCUS.PRICLIST
and [CURRENCY] = 'CDN' and DPRICETYPE = 1
and (itemgroup like '%' + #search + '%' or itemtype like '%' + #search + '%' or itembrand like '%' + #search + '%'
or subcat like '%' + #search + '%' or orderformdump.description like '%' + #search + '%' or basedescription like '%'+ #search + '%'
or orderformdump.ITEMNO like '%'+#search+'%' or UPC like '%'+#search+'%' or (select top 1 1 from pppltd.dbo.ICITEMO where OPTFIELD like 'UPC%' and VALUE like '%'+#search+'%'
and ITEMNO = DataWarehouse.dbo.ORDERFORMDUMP.itemno) is not null)
group by ORDERFORMDUMP.ITEMNO,BASEDESCRIPTION,info,UPC,CAST(UNITPRICE AS DECIMAL(18,2)),caseqty
order by basedescription
to LINQ:
var qty = db.WebOEOrdD.Sum(d => d.QTY);
var unitPrice = db.IcPricP.Select(p => decimal.Round(p.UNITPRICE, 2));
var query = from item in dbData.OrderFormDump
join icp in db.IcPricP on item.ITEMNO.Replace("-", "") equals icp.ITEMNO
join itemInfo in db.WebItemInfo on item.ITEMNO equals itemInfo.ITEMNO
join weboeordh in db.WebOEOrdH on username equals weboeordh.USER
join weboeordd in db.WebOEOrdD on new { itemno = item.ITEMNO.Replace("-", ""), orduniq = weboeordh.ORDUNIQ } equals new { itemno = weboeordd.ITEMNO, orduniq = weboeordd.ORDUNIQ }
join weboeordsubmit in db.WebOEOrdSubmit on weboeordd.ORDUNIQ equals weboeordsubmit.ORDUNIQ where weboeordsubmit.ORDUNIQ != weboeordd.ORDUNIQ
join webloginaccess in db.WebLoginAccess on username equals webloginaccess.USER
join arcus in db.Arcus on webloginaccess.CUSTID equals arcus.IDCUST
where (item.ALLOWINBC == "Yes" && item.ALLOWINAB == "Yes")
&& icp.PRICELIST == arcus.PRICLIST
&& icp.CURRENCY == "CDN" && icp.DPRICETYPE == 1
&& (item.BASEDESCRIPTION.Contains(searchword) || item.DESCRIPTION.Contains(searchword) || item.CATEGORY.Contains(searchword) || item.FOODACCSPEC.Contains(searchword) || item.ITEMBRAND.Contains(searchword) || item.ITEMGROUP.Contains(searchword) || item.ITEMNO.Contains(searchword) || item.ITEMSUBTYPE.Contains(searchword) || item.ITEMTYPE.Contains(searchword) || itemInfo.INFO.Contains(searchword) || item.UPC.Contains(searchword) || item.UPC.Substring(2, 10).Contains(searchword))
orderby item.BASEDESCRIPTION
group item by new { item.ITEMNO, item.BASEDESCRIPTION, itemInfo.INFO, item.UPC, unitPrice, item.CASEQTY, qty } into items
select new { items.Key.ITEMNO, items.Key.BASEDESCRIPTION, items.Key.INFO, items.Key.UPC, unitPrice, items.Key.CASEQTY, qty };
Am I converting it correctly? Do I have to create two separate queries and combine them? Lastly, can I combine two different databases into one dbContext? If so, how do I do this?
Thank you.
UPDATE
I tried adding tables from another database into my main dbContext and I'm getting this error:
The entity type ORDERFORMDUMP is not part of the model for the current context.
UPDATE #2
What I did to solve my problem doesn't really answer this question, however it is a good workaround.
What I did was I took the only table in my query that was part of a different DbContext and another database (ORDERFORMDUMP), and I copied that table to the main database in SQL Server. As a result, I was able to add that table to my main DbContext.
There are a couple ways of accomplishing this.
I would recommending creating a view of your query, then bind it to a new linq object, and then you can query off of that. Trying to write your query fully in linq is possible, but it would just get nasty, given you are working with multiple data contexts.
You are going to have to have two different queries, materialize the query results, then do whatever operations you want to do on them in memory.
What I did to solve my problem doesn't really answer this question, however it is a good workaround.
What I did was I took the only table in my query that was part of a different DbContext and another database (ORDERFORMDUMP), and I copied that table to the main database in SQL Server. As a result, I was able to add that table to my main DbContext.
Related
I have the following table structure of my database:
db structure
My aim is to output every row of tbl_Therapeuten (these are my employees) with the name of their trainings (in german "Fortbildung").
The names of the trainings are stored in tbl_Forbildungen. And the trainings which each employee has is stores in tbl_Therapeut_Fortbildung. For the output I want to show the name of the training, not the id.
Like this:
output
I am programming in C#, SQL Server.
First I tried this:
string sSQL = "SELECT t.*, STRING_AGG(tf.Id_Fortbildung, ';') AS Fortbildungen " +
"FROM tbl_Therapeuten t " +
"FULL OUTER JOIN tbl_Therapeut_Fortbildung tf on t.Id = tf.Id_Therapeut ";
But this brings an error containing that I don't use tbl_Therapeuten.Id in an aggregate function or in a Group by clause.
Next I tried this:
string sSQL = "SELECT t.Id, t.Nachname, STRING_AGG(tf.Id_Fortbildung, ';') AS Fortbildungen " +
"FROM tbl_Therapeuten t " +
"FULL OUTER JOIN tbl_Therapeut_Fortbildung tf on t.Id = tf.Id_Therapeut " +
"GROUP BY t.Id, t.Nachname";
This worked (except displaying the name of the training but the Id) but I don't want to explicitly name every column of tbl_Therapeuten. I want to use "t.*". But this is not working:
string sSQL = "SELECT t.*, STRING_AGG(tf.Id_Fortbildung, ';') AS Fortbildungen " +
"FROM tbl_Therapeuten t " +
"FULL OUTER JOIN tbl_Therapeut_Fortbildung tf on t.Id = tf.Id_Therapeut " +
"GROUP BY t.*";
So I need some help :)
And what I also don't know how to do is to display the name of the trainings instead of the id.
Thanks for your help!
You might find that a correlated subquery provides better performance (by avoiding the outer aggregation) and allows you to avoid listing all columns from t:
SELECT T.*,
(SELECT STRING_AGG(F.Name, ';')
FROM tbl_Therapeut_FortBildung TF JOIN
tbl_FortBildungen F
ON F.Id = TF.Id_FortBildung
WHERE TF.Id_Therapeut = T.Id
) as Fortbildungen
FROM Therapeuten T
I think this is what you need.
SELECT T.Id,T.Name,T.Street,T.BirthDate,STRING_AGG(F.Name,';')
FROM Therapeuten T
LEFT JOIN tbl_Therapeut_FortBildung TF ON TF.Id_Therapeut=T.Id
LEFT JOIN tbl_FortBildungen F ON F.Id=TF.Id_FortBildung
GROUP BY T.Id,T.Name,T.Street,T.BirthDate
As far as I know SQL server does not support the GROUP BY *, so you will have to specify the column names.
We need to convert following query to Entity framework syntax based query but not fond any alternative for '<>' condition:
Query:
select (FirstName+' '+LastName) AS Name ,WorksNumber from [TSHumanResource]
join [TSUserProfile] on [TSUserProfile].[TSPersonID] = [TSHumanResource].[TSPersonID]
join [TSPerson] on [TSPerson].[TSPersonID] = [TSHumanResource].[TSPersonID]
where [TSUserProfile].[TSUserStatusID] = 1
and [EmployeeReference] <> ' ' and [MMSUserID] is not null order by [WorksNumber] asc
Here's what I was tring:
(from HR in oDB.TSHumanResources
join UP in oDB.TSUserProfiles on HR.TSPersonID equals UP.TSPersonID
join P in oDB.TSPersons on HR.TSPersonID equals P.TSPersonID
where UP.TSUserStatusID == 1 && HR.EmployeeReference <>
select new
{
ID = e.TSPersonID ,
ID = e.TID,
}).Take(10);
The SQL Server operator <> means not equal. In c#, the not equal operator is written like this: !=.
You have another problem in your linq query - you are currently doing an inner join instead of a left join.
A left join in LINQ is a bit cumbersome comparing to a left join in SQL - it has to go through a group join first. Your query should look more like this:
from hr in TSHumanResource
join up in TSUserProfile on hr.TSPersonID equals up.TSPersonID into upgroup
from upg in upgroup.DefaultIfEmpty()
join p in TSPerson on upg.TSPersonID equals p.TSPersonID into pgroup
from puphr in pgroup.DefaultIfEmpty()
where up.TSUserStatusID = 1
&& HR.EmployeeReference != " " // Assuming you want it different than a single space
// Other conditions here - I don't know where MMSUserID belongs to
order by hr.WorksNumber // just guessing here - I don't know if it's from hr
I'm using Telerik Open Access. I have two separate projects that have Open Access data and then a third project that has the bulk of my code. I've been working on a way to convert a simple (at least I thought it was) SQL query to LINQ so that I can get the data I need. I have not been successful. I've had to break a single LINQ query into separate queries, because of the need for the Trim() function (I think). This has led to a lengthy piece of code and I'm still not getting the same results as my SQL query.
So my question is, is there anyway to use SQL instead of LINQ to access the data in the Open Access projects? If so, can you show me the syntax to do that for my query?
If it is not possible to use SQL, can you show me show me the proper way to convert my SQL query into LINQ so that I get the same results?
Thank you.
My SQL query is
SELECT DISTINCT us2.ccustno, us2.dispname, us2.csiteno, so.s1_name
FROM [DALubeDeacom].[dbo].[dmbill] bi
INNER JOIN [DALubeDeacom].[dbo].[dmso1] so
ON bi.bi_s1id = so.s1_id
INNER JOIN [DALubeNew].[dbo].[usersecurity] us2
ON so.s1_name = us2.cparentno
WHERE
us2.ctype = 'JOBSITE'
AND us2.csiteno is not null
AND us2.csiteno != ''
AND bi.bi_smid = '22'
ORDER BY us2.csiteno
My LINQ query is
public List<DataModelSample> GetLocationsBySalesNo(string salesNo)
{
int iSalesNo = int.Parse(salesNo.Trim());
try
{
var dmso = (
from so in deacom.Dmso1
join qt in deacom.Dmbills
on so.S1_id equals qt.Bi_s1id
where qt.Bi_smid == iSalesNo
select new Dmso1
{
S1_id = so.S1_id
, S1_name = so.S1_name.Trim()
}
);
var usec = (
from us in dbContext.Usersecurities
where us.Cparentno != null && us.Cparentno.Trim() != "" && us.Ctype.Trim() == "JOBSITE" && us.Csiteno.Trim() != ""
select new Usersecurity
{
Ccustno = us.Ccustno.Trim(),
Csiteno = us.Csiteno.Trim(),
Dispname = us.Dispname.Trim(),
Cparentno = us.Cparentno.Trim()
}
);
var customers =
(
from us in usec
join so in dmso
on us.Cparentno equals so.S1_name
select us
);
customers = customers.GroupBy(x => x.Csiteno).Select(x => x.First());
List<DataModelSample> listLocations =
(
from c in customers
select new DataModelSample
{
customerID = c.Ccustno
,
origLocationName = c.Csiteno + " " + c.Dispname
,
origLocationID = c.Csiteno
}
).OrderBy(x => x.origLocationID).ToList();
return listLocations.ToList();
}
catch (Exception ex)
{
throw ex;
}
} // GetLocationsBySalesNo(userInfo.csalesno)
Edit 1 - 2-19-16
Tried a suggestion by ViktorZ. His query was similar to the one I first tried. It returned the error "Identifier 'Ctype' is not a parameter or variable or field of 'DALube_DeacomModel.Dmbill'. If 'Ctype' is a property please add the FieldAlias or Storage attribute to it or declare it as a field's alias." From an online search, it looked like this was do to "extended fields". I don't seemed to be using such fields. The only way I could get around this error was to break it into the smaller LINQ queries in my original question, which didn't produce the right results. Any suggestions?
Here's the code:
var query = (from bill in deacom.Dmbills
join so in deacom.Dmso1 on bill.Bi_s1id equals so.S1_id
join us in dbContext.Usersecurities on so.S1_name equals us.Cparentno
where us.Ctype == "JOBSITE"
&& us.Csiteno != null
&& us.Csiteno != string.Empty
&& bill.Bi_smid == iSalesNo
select new
{
ccustno = us.Ccustno.Trim(),
dispname = us.Dispname.Trim(),
csiteno = us.Csiteno.Trim(),
s1_name = so.S1_name.Trim()
}).Distinct();
One very crude approximation of your SQL query is:
var query = (from bill in deacom.Bills
join so in deacom.LubeDeacom on bill.bi_s1id equals so.s1_id
join us in deacom.UserSecurity on so.s1_name equals us.cparentno
where us.ctype = "JOBSITE"
&& us.csiteno != null
&& us.csiteno != string.Empty
&& bill.smid = '22'
order by us.csiteno
select new
{
us.ccustno.Trim(),
us.dispname.Trim(),
us.csiteno.Trim(),
so.s1_name.Trim()
}).Distinct();
// to check the translation result
string sql = query.ToString()
// to get the results
var result = query.ToList()
If this is not working for you, you can always fall back to Telerik Data Access ADO.NET API. Here is a documentation article how to use it.
I have a Linq Query that works well but I need to write the SQL Query
Can Anybody help me write it?
this query will search the database foreach a.h and a.HV in the view with the filters of time and model and in the end it checks the option Filter.M that if it is selected it will search for all the data selected in this DropDownCheckBoxes`
How can i write the this where and select part in SQL command?
ret1 = (from a in View
where
a.LastRefreshTime>=Filter.From && a.LastRefreshTime<=Filter.To && a.ModelCode == mdlCode &&
Filter.PN.Select(epn => epn.Substring(0, 11)).Contains(a.H) &&
Filter.PN.Select(epn => epn.Substring(14, 2)).Contains(a.HV)
select new RData
{
v = a.v,
Date = a.LastRefreshTime,
UserId = a.UserId,
M = a.Name,
}).Distinct().AsQueryable();
ret = ret1.Where(nr =>
Filter.M == null || !Filter.M.Any() || Filter.M.Contains(nr.M)
).ToList();
Here's a start for you
select a.v v,
a.LastRefreshTime "Date",
a.UserId,
a.Name
from a
where a.LastRefreshTime>= arg_filter_from
and a.LastRefreshTime<= arg_filter_to
and a.ModelCode = arg_mdlCode
.
.
.
In this query you'll need to replace 'arg_...' with the appropriate values or arguments you want.
Contains is roughly equivalent to "IN" in SQL. For example:
where a.Name in ('jim', 'bob', 'joe')
In can also be used with a subselect which is roughly what I think Filter.PN.Select is doing though I'm not a linq expert. Example:
where a.H in (Select foo from PN_Table)
Or simpler example continuing on the my previous name example:
where a.Name in (select first_name from table)
If we supposed that the Filter.PN list represent a table FilterPN in your sql database, that will be your converted code for the first linq query
select distinct a.v, a.LastRefreshTime, a.UserId, a.Name
from [view] a
where a.LastRefreshTime>= 'Filter.From' and
a.LastRefreshTime<='Filter.To' and a.ModelCode = 'mdlCode' and
exists(select top 1 * from FilterPN where Substring(epn, 1, 11) = a.H) and
exists(select top 1 * from FilterPN where Substring(eenter code herepn, 15, 2) = a.HV)
think to replace the enquoted variables with ur real values 'Filter.To'...
Database structure sample:
Department Table
-DepartmentID
Facility Table
-Facility ID
-DepartmentID (FK)
-Block
-Level
-Name
-etc
I am trying to select from database from the EF using two where clause. I am not sure what went wrong at the where clause. I am stuck at it. Please help and advice. I have googled on the internet but cannot find the solution to it.
string departmentID = "SIT";
string block = "L";
string level = "4";
string name = "L.425";
using (var db = new KioskContext())
{
var facilitys = from f in db.Facilitys
Where clause to select departmentID where equals to SIT and also where any block or level or name contains any alphabets. Please advice how should i write the statement with two where clause. Thank You!
where f.Department.DepartmentID == departmentID
&& (f.Block.Contains("%" + block + "%") || f.Level.Contains("%" + level + "%")
|| f.Name.Contains("%" + name + "%"))
Remaining of the query statement to select all the facilities
orderby f.FacilityID
select new
{
f.FacilityID,
f.DepartmentID,
f.Description,
f.Block,
f.Level,
f.Name,
f.OpenHours,
f.CloseHours,
f.MaxBkTime,
f.MaxBkUnits,
f.MinBkTime,
f.MinBkUnits
};
foreach (var fac in facilitys)
{
FacObject facobject = new FacObject(fac.FacilityID, fac.DepartmentID, fac.Description, fac.Block, fac.Level,
fac.Name, fac.OpenHours, fac.CloseHours, fac.MaxBkTime, fac.MaxBkUnits, fac.MinBkTime, fac.MinBkUnits);
sqlFacList.Add(facobject);
}
}
Remove the "%" from the various Contains clauses, they are SQL cruft you do not need.
where f.Department.DepartmentID == departmentID
&& (f.Block.Contains(block)
|| f.Level.Contains(level)
|| f.Name.Contains(name ))
Remember LINQ is not just for SQL!