Linq Query for Complex Object - linq

Everyone - I have the following set of objects:
User { String:Name, List<Devices> }
Device {String:Name, DeviceVariationInfo }
DeviceVariationInfo { String:OS }
In the database those object are split into the following tables:
Users, Devices, DevieVariationsInfo, UserToDevices
I am trying to query the the list of devices along with their variation info for a certain user, and am using the following query, which always returns a list of 0 items in Devices. I am pretty sure I am doing something wrong here.. =)
private void GetUserDevices(ref User user)
{
User locUSer = user;
if (user != null)
{
var deviesQuery = from dts in _dataConext.DB_UserToDevices
where dts.UserId == locUSer.Id
join ds in _dataConext.DB_Devices on dts.DeviceID equals ds.Id
join dsv in _dataConext.DB_DeviceVariations on ds.Id equals dsv.DeviceId
select new Device
{
Version = ds.Version,
VariationInfo = new DeviceVariation
{
OSVersion = dsv.OS
},
Name = ds.FriendlyName,
Id = ds.Id
};
if (deviesQuery != null)
user.Devices = deviesQuery.ToList();
}
}

A couple of notes:
Is User a class? If so, why are you passing it into GetUserDevices by ref? Don't do that unless you want to change the meaning of that reference.
Also, why are you doing this? User locUSer = user;
Here's how I'd go about debugging your problem: remove parts of that query until you get data back. For example, remove the last join statement, rerun the query, and see where you're going wrong.

Related

Associate user when created with an existing Account

I have a code that checks an inquery database a for user,
If the user does not exist, then the code will create a new user in Contact,
Here is only part of the code:
newcontact = [SELECT Id, FirstName FROM Contact WHERE Contact.Email =inquery.email__c];
if(newcontact.size() == 0) {
Account[] aa = [SELECT Id FROM Account WHERE Name = :inquery.Institution__c];
contact = new Contact();
contact.FirstName = inquery.First_Name__c;
contact.LastName = inquery.Last_Name__c;
contact.Email = inquery.email__c;
contact.AccountId = aa.Id;
try {
insert contact; // inserts the new record into the database
} catch (DMLException e) {
ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error creating new contact'));
return null;
}
I am trying to associate that user with an existing Account?
But the following line gives me an error:
contact.AccountId = aa.Id;
Which is
Initial term of field expression must be a concrete SObject: LIST<Account> at line
And aa.size() returns 1, as it should,
Because the account exists,
Can someone please tell me what wrong?
Thanks
This line contact.AccountId = aa.get(0).Id; will fail if your query returns 0 rows. Make sure to wrap your code within a if (aa.size() > 0) clause to ensure proper execution in all cases.
Ok I fixed it, as follows:
contact.AccountId = aa.get(0).Id;
Best

LINQ to Entities does not recognize the method 'System.String get_Item(System.String)' method

I've looked at the various solutions here but none of them seem to work for me, probably because I'm too new to all this and am groping in the dark a bit. In the code below, the object "appointment" contains some basic LDAP information. From a list of such objects I want to be able to get a single record, based on employee id. I hope the code here is sufficient to illustrate. FTR, I've tried various formulations, including trying to use from and a select. All fail with the error given in the Title above.
IQueryable<appointment> query = null;
foreach(var record in results)
{
BoiseStateLdapDataObject record1 = record;
query = db.appointments.Where(x => x.student_id == record1.Values["employeeid"]);
}
if (query != null)
{
var selectedRecord = query.SingleOrDefault();
}
Try to move employee id getting out of query:
IQueryable<appointment> query = null;
foreach(var record in results)
{
var employeeId = record.Values["employeeid"];
query = db.appointments.Where(x => x.student_id == employeeId);
}
if (query != null)
{
var selectedRecord = query.SingleOrDefault();
}

How to create a update function in LINQ when object has a list?

I´m still having a hard time with Linq.
I need to write a Update Function tat receives an object that has a list. Actually, A region has a list of cities. I want to pass an object "Region" that has a name filed and a list of cities. The problem, is the city objects came from another context and I am unable to attach them to this context. I have been trying several functions, and always get an error like "EntitySet was modified during enumeration" or other. I am tring to make the code below work, but if anyone has a different approach please help.
public int Updateregion(region E)
{
try
{
using (var ctx = new AppDataDataContext())
{
var R =
(from edt in ctx.regiaos
where edt.ID == E.ID
select edt).SingleOrDefault();
if (R != null)
{
R.name = R.name;
R.description = E.description;
}
R.cities = null;
R.cities.AddRange(Edited.Cities);
ctx.SubmitChanges();
return 0 //OK!
}
}
catch (Exception e)
{
......
}
You can't attach objects retrieved from one datacontext to another, it's not supported by Linq-to-SQL. You need to somehow dettach the objects from their original context, but this isn't supported either. One can wonder why a dettach method isn't available, but at least you can fake it by mapping the list to new objects:
var cities = Edited.Cities.Select(city => new City {
ID = city.ID,
Name = city.Name,
/* etc */
});
The key here is to remember to map the primary key and NOT map any of the relation properties. They must be set to null. After this, you should be able to attach the new cities list, and have it work as expected.

Linq one to many insert when many already exists

So I'm new to linq so be warned what I'm doing may be completely stupid!
I've got a table of caseStudies and a table of Services with a many to many relasionship
the case studies already exist and I'm trying to insert a service whilst linking some case studies that already exist to it. I was presuming something like this would work?
Service service = new Service()
{
CreateDate = DateTime.Now,
CreatedBy = (from u in db.Users
where u.Id == userId
select u).Take(1).First(),
Description = description,
Title = title,
CaseStudies = (from c in db.CaseStudies
where c.Name == caseStudy
select c),
Icon = iconFile,
FeatureImageGroupId = imgGroupId,
UpdateDate = DateTime.Now,
UpdatedBy = (from u in db.Users
where u.Id == userId
select u).Take(1).First()
};
But This isn't correct as it complains about
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Objects.DataClasses.EntityCollection'
Can somebody please show me the correct way.
Thanks in advance
Yo have to add the query result to the case studies collection instead of trying to replace it.
var service = new Service { ... };
foreach (var caseStudy in db.CaseStudies.Where(s => s.Name == caseStudyName)
{
service.CaseStudies.Add(caseStudy);
}
You can wrap this in an extension method and get a nice syntax.
public static class ExtensionMethods
{
public static void AddRange<T>(this EntityCollection<T> entityCollection,
IEnumerable<T> entities)
{
// Add sanity checks here.
foreach (T entity in entities)
{
entityCollection.Add(entity);
}
}
}
And now you get the following.
var service = new Service { ... };
service.CaseStudies.AddRange(db.CaseStudies.Where(s => s.Name == caseStudyName));

linq help - newbie

how come this work
public IQueryable<Category> getCategories(int postId)
{
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
var query = from c in categories.GetAll()
join pcm in postCategoryMap.GetAll() on c.CategoryId equals pcm.CategoryId
where pcm.PostId == 1
select new Category
{
Name = c.Name,
CategoryId = c.CategoryId
};
return query;
}
but this does not
public IQueryable<Category> getCategories(int postId)
{
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
var query = from c in categories.GetAll()
join pcm in postCategoryMap.GetAll() on c.CategoryId equals pcm.CategoryId
where pcm.PostId == postId
select new Category
{
Name = c.Name,
CategoryId = c.CategoryId
};
return query;
}
The issue is most likely in the implementation of the query provider.
pcm.PostId == 1
and
pcm.PostId == postId
actually have a big difference. In the expression tree the first is generated as a ConstantExpression which doesnt need to be evaulated.
With the second, the compiler actually generates an inner class here (this is the _DisplayClassX that you see). This class will have a property (will most likely be the same name as your parameter) and the expression tree will create a MemberAccessExpression which points to the auto-generated DisplayClassX. When you query provider comes accross this you need to Compile() the Lambda expression and evaluate the delegate to get the value to use in your query.
Hope this helps.
cosullivan
The problem is not the linq itself,
you need to be sure that the context or provider object is able to fetch the data.
try testing the
subnusMVCRepository<Categories> categories = new subnusMVCRepository<Categories>();
subnusMVCRepository<Post_Category_Map> postCategoryMap = new subnusMVCRepository<Post_Category_Map>();
objects and see if they are populated or if they behaving as required.
you may want to search the generated code for c__DisplayClass1 and see what you can see there. some times the generated code dose some weird things.
when you step into you code check the locals and the variable values. this may also give you some clues.
Edit : Have you tried to return a List<> collection ? or an Enumerable type?
Edit : What is the real type of the item and query may not be iterable

Resources