So I have a table called groupe_stg it contains 2 foreign keys code_demande , code_stagiaire and at the same time they are primary keys.
In my app I have the code_stagiaire and from it I want to retrieve it's code_demande. Basically what am trying to say is:
select code_demande
from group_stg
where code_stagiaire = "parameter"`
I would've create a stored procedure it would be easier , but unfortunately I was forced to work with an access database
This is my solution for the LINQ code,
String code_linq()
{
var query = from g in Program.mds.group_stg
where g.cin_stagiaire == txt_cin.Text
select new
{
code = g.code_demande
};
return query.ToString();
}
As you can see it is some sort a scalar function
but this code is giving me this exception:
system.data.enumerablerowcollection'1 [<>
f_anonymousType0'1[System.String]]
You are selecting multiple code_demande in an anonymous type but you want a single string.
If you just want the first code_demande which has cin_stagiaire == txt_cin.Text:
var demands = from g in Program.mds.group_stg
where g.cin_stagiaire == txt_cin.Text
select g.code_demande;
return demands.FirstOrdefault(); // null if no match
Related
String priceID = codeArray[0];
var priceResult = from PRICE_LIST in priceContext.PRICE_LIST
where PRICE_LIST.PRICE_ID == priceID
select new
{
PRICE_LIST.RETAIL,
PRICE_LIST.WHOLESALE
}.ToList();
I'm receiving a compile error that the anonymous type does not contain a definition for ToList() and I'm not sure why? I've seen many examples where queries are stored using this method. I can do priceResult.ToList(), but both the retail and wholesale price columns are in the same list element. So I can't get retail by selecting the first element ect. New to EF & LINQ and still on the learning curve.
You need to put the entire LINQ within parentheses like this:
var priceResult = (from PRICE_LIST in priceContext.PRICE_LIST
where PRICE_LIST.PRICE_ID == priceID
select new
{
PRICE_LIST.RETAIL,
PRICE_LIST.WHOLESALE
}).ToList();
otherwise it tries to make each new object to a list
In a block of code I have a Foreach that I use to run through and count specific pieces that may or may not exist in the database. Basically for each part on an Order, I go on to count the Product Groups those belong to and then the Division those Product Groups belong to. For that I use this LINQ query:
foreach (var OrderDtl_yRow in ( from ThisOrderDtl in Db.OrderDtl
join ThisProdGrup in Db.ProdGrup on
ThisOrderDtl.ProdCode equals ThisProdGrup.ProdCode
where
ThisOrderDtl.Company == Session.CompanyID &&
ThisOrderDtl.OrderNum == 195792
select new
{
ProdCode = ThisOrderDtl.ProdCode,
Division = ThisProdGrup.Division_c,
OrderNum = ThisOrderDtl.OrderNum,
OrderLine = ThisOrderDtl.OrderLine
}))
{ ....counting things... }
Currently I've got message boxes set up to return the values to me as the process is going. I get everything to return correctly except the Division, that always shows up as blank in the MessageBoxes (So NULL I'd assume). So my Counters for Division don't Increment.
If I take that out into LINQPad I'm unsure how to return results of a foreach, but I tried it with
if(OrderDtl_yRow.Division != null && OrderDtl_yRow.Division != "")
{i++;}
i.Dump();
and got 5 (There were 5 rows I expected so I'm at least pulling our something). Then I converted it to a simpler FirstOrDefault statement to test a single value like
var OrderDtl_yRow = ( from ThisOrderDtl in OrderDtl
join ThisProdGrup in ProdGrup on
ThisOrderDtl.ProdCode equals ThisProdGrup.ProdCode
where
ThisOrderDtl.OrderNum == 195792 &&
ThisOrderDtl.OrderLine == 1
select new
{
ProdCode = ThisOrderDtl.ProdCode,
Division = ThisProdGrup.Division_c,
OrderNum = ThisOrderDtl.OrderNum,
OrderLine = ThisOrderDtl.OrderLine
}).FirstOrDefault();
Then if I do a OrderDtl_yRow.Dump() I get my result and sure enough, Division comes through. So all signs point to it being fine, yet I can't bring over the value where I actually need it to show up. Thoughts? Thanks!
P.S. For those familiar with Epicor ERP Division is a UD field, so it technically belongs to the table ProdGrup_UD, but in Epicor it recognized that as the table ProdGrup just fine, its only SQL that makes you join _UD to the parent table. I tried joining it anyways for funsies and it didn't like it because it knew the column was there already. So that should be fine.
UPDATE: Rookie Move, didn't upload the Division data into the testing environment, so nothing was there, then checked against Live data where it existed and scratched my head as to why it didn't match. But I learned something about LinqPad and Linq so it wasn't a useless exercise.
You need to play some more in Linqpad to see what is happening, Set the language to C# program, Press F4 and add references to Server\Bin\Epicor.System.dll and Server\Assemblies\Erp.Data.910100.dll and point the app.copnfig to your Server\web.config file. In the main block create yourself a Db context with var Db = new Erp.ErpContext();
Linqpad can display complex data structures so you needn't have done FirstOrDefault in your last example. for instance:
void Main()
{
var Db = new Erp.ErpContext();
var sessionCompany = "EPIC06";
var x = (from hed in Db.OrderHed
join dtl in Db.OrderDtl
on new { hed.Company, hed.OrderNum }
equals new { dtl.Company, dtl.OrderNum }
into dtlList
where
hed.Company == sessionCompany
select new { hed, dtlList })
.Dump();
}
Also note that in SQL dbo.ProdGrup is an autogenerated view that joins the tables Erp.ProdGrup and Erp.ProdGrup_UD for you.
I have 3 tables in my DB which I'm working with:
Theme [Theme_ID]
ThemeWorkplace [Theme_ID, Workplace_ID, ThemeWorkplace_ID]
UserTheme [User_ID, Theme_ID, UserTheme_ID, UserTheme_AccessType]
I need to change UserTheme_AccessType for all UserTheme.Theme_ID in current workplace with ThemeWorkplace.Workplace_ID = 2 and current user with User_ID = 1. If theme is no row in UserTheme for such user and such theme - I need to create it.
I wrote such a code, but it works too long time:
var themeList = (from t in m_Entities.Theme
where (from tw in m_Entities.ThemeWorkplace
where tw.Workplace.Workplace_ID == 2
select tw.Theme.Theme_ID).Contains(t.Theme_ID)
select t)
.ToList();
foreach (Theme theme in themeList)
{
var oldUserTheme = GetByUserTheme(user/*user is given*/, theme);
if (oldUserTheme == null)
{
/* create new User Theme with params, that I need*/
this.Add(newUserTheme, true);
}
else
{
/* here - changing found row */
oldUserTheme.UserTheme_AccessType = 2;
}
}
I understand that this code accesses the database too many times. I want to find a way to get rid of:
var oldUserTheme = GetByUserTheme(user/*user is given*/, theme);
In every foreach iteration. Could somebody please help me?
Adding code of GetByUserTheme():
private UserTheme GetByUserTheme(User user, Theme theme)
{
return m_Entities.UserTheme.FirstOrDefault(ut => ut.User.User_ID == user.User_ID && ut.Theme.Theme_ID == theme.Theme_ID);
}
First: All changes for entities that you have done in code will be pushed to database in one batch command when you call context.SaveChanges. So you will have one request to Database for select and one request for update.
But in your batch command will be many sql queries for cause EF generate sql for updates entities one by one (not all in one).
If you want update really many records in database, you should use sql script (call stored procedure or execute sqlquery) against using EntityFramework.
I don't know if I'm completely understanding your question and structure. But based on what I see, could this be a reasonable slution?
First you select the workplaces that have ID equal to 2. From that result you select the theme-ID's. All your userthemes that have a themeID that occurs in the former result will then be selected into 'userThemes'. From there, you iterate over the results and if the userID is empty you create a new UserTheme, otherwise you update it.
Quick note: the code below is no real working code. It's just code I wrote to exemplify my explanation, kind of pseudo-code if you will.. :)
var userThemes = entities.Userthemes
.Where(ut => entities.Workplaces
.Where(w => w.WorkPlaceID == 2)
.Select(s => s.ThemeID)
.Contains(ut.ThemeID));
foreach (UserTheme ut in userThemes)
{
if (ut.UserID.ToString() == "")
{
//Create
}
else
ut.UserThemeAccessType = 2;
}
I am a newbe to C# and have to use it for my master thesis. At the moment, I am facing a problem that is a bit to complex for me.
I have set up a database with a many-to-many relationship like this:
Table Relay:
- id (PK)
- Name
- Input
Table ProtectionFunction:
- id (PK)
- ANSI
- IEC
- Description
Table RelayConfig (junction table)
- RelayID (PK)
- ProtFuncID (PK)
- TimeToSaturate
- Remanence
The thing is, a Relay can have multiple protection functions, and for each it has specific values for TimeToSaturate and Remanence. Now I want to realize a filter. The user can select protection function via checkboxes in a DataGridView and a ListBox should show all Relays that support ALL of these protection functions.
I have already created the LINQ-to-SQL classes for my project. But now I am stuck because I don't know how to realize the filtering. All LINQ commands I have found so far would give me all Relays for one protection function.
I really hope one of you can give me a hint.
var ids = new int[]{ ... };
// if ids is null or ids.Length == 0 please return null or an empty list,
//do not go further otherwise you'll get Relays without any function filter
var query = Relays.AsQueryable();
foreach (var id in ids)
{
var tempId = id;
query = query.Where(r=>r.RelayConfigs.Any(rc=>rc.ProtFuncID == tempId));
}
var items = query.ToList();
Update
Just saw this on PredicateBuilder page:
The temporary variable in the loop is required to avoid the outer
variable trap, where the same variable is captured for each iteration
of the foreach loop.
It's easier if you start from the RelayConfigs. Something like this should work:
var protFuncIds = new[]{1,2,3};
var query = from rc in db.RelayConfigs
where protFuncIds.Contains(rc.ProtFuncID)
select rc.Relay;
var relays = query.Distinct().ToList();
UPDATE:
based on your comment, the following should work, however do monitor the SQL generated...
IQueryable<Relay> query = db.Relays
foreach (var id in ids)
query = relays.Where(r => r.RelayConfigs.Select(x => x.ProtFuncId).Contains(id));
var relays = query.ToList();
// Build a list of protection function ids from your checkbox list
var protFuncIDs = [1,2,3,4];
using(var dc = new MyDataContext())
{
var result = dc.Relays.Where(r=>protFuncIDs.Join(r.RelayConfigs, pf=>pf, rc=>rc.ProtFuncID, (pf,rc)=>pf).Count() == protFuncIDs.Length).ToArray();
}
It's not especially efficient, but that should do the trick for you.
I have done this in Lightswitch, and here was my preprocess query:
partial void UnusedContactTypesByContact_PreprocessQuery(int? ContactID, ref IQueryable<ContactType> query)
{
query = from contactType in query
where !contactType.ContactToContactTypes.Any(c => c.Contact.Id == ContactID)
select contactType;
}
Hope that helps.
with my Repository classes, I use LinqToSql to retrieve the data from the repository (eg. Sql Server 2008, in my example). I place the result data into a POCO object. Works great :)
Now, if my POCO object has a child property, (which is another POCO object or an IList), i'm trying to figure out a way to populate that data. I'm just not too sure how to do this.
Here's some sample code i have. Please note the last property I'm setting. It compiles, but it's not 'right'. It's not the POCO object instance .. and i'm not sure how to code that last line.
public IQueryable<GameFile> GetGameFiles(bool includeUserIdAccess)
{
return (from q in Database.Files
select new Core.GameFile
{
CheckedOn = q.CheckedOn.Value,
FileName = q.FileName,
GameFileId = q.FileId,
GameType = (Core.GameType)q.GameTypeId,
IsActive = q.IsActive,
LastFilePosition = q.LastFilePosition.Value,
UniqueName = q.UniqueName,
UpdatedOn = q.UpdatedOn.Value,
// Now any children....
// NOTE: I wish to create a POCO object
// that has an int UserId _and_ a string Name.
UserAccess = includeUserIdAccess ?
q.FileUserAccesses.Select(x => x.UserId).ToList() : null
});
}
Notes:
Database.Files => The File table.
Database.FilesUserAccess => the FilesUserAccess table .. which users have access to the GameFiles / Files table.
Update
I've now got a suggestion to extract the children results into their respective POCO classes, but this is what the Visual Studio Debugger is saying the class is :-
Why is it a System.Data.Linq.SqlClient.Implementation.ObjectMaterializer<..>
.Convert<Core.GameFile> and not a List<Core.GameFile> containing the POCO's?
Any suggestions what that is / what I've done wrong?
Update 2:
this is what i've done to extract the children data into their respective poco's..
// Now any children....
UserIdAccess = includeUserIdAccess ?
(from x in q.FileUserAccesses
select x.UserId).ToList() : null,
LogEntries = includeUserIdAccess ?
(from x in q.LogEntries
select new Core.LogEntry
{
ClientGuid = x.ClientGuid,
ClientIpAndPort = x.ClientIpAndPort,
// ... snip other properties
Violation = x.Violation
}).ToList() : null
I think that all you need to do is to put another Linq query in here:
q.FileUserAccesses.Select(x => x.UserId).ToList()
i.e. You want to select data from the FileUserAccess records - which I'm assuming are Linq to SQL classes, so to do this you can have something like:
(from fua in q.FileUserAccesses
select new PocoType
{
UserID = fua.UserID,
Name = fua.User.UserName // Not sure at this point where the name comes from
}).ToList()
That should get you pointed in the right direction at least.
What is the type of UserIdAccess? How is it not 'right'? Are you getting the 'wrong' data? if so have you checked your database directly to make sure the 'right' data is there?