Getting strings from LINQ queries in Sharepoint web part? - linq

I'm setting up a Sharepoint Web Part for tracking language translations for our various products. I can create the translations, now I'm trying to re-populate the form controls if someone chooses an item that that already has a translation, ie they select "French-ProductX" and the various texboxes populate with the data for that translation/product.
My LINQ query is pulling the right data (itemname is the product the user has chosen in a dropdown menu).
var query = from translation in Translations
where (Convert.ToString(translation.Name)) == itemname
select translation;
I can bind the query to a grid and see i'm getting the correct data, but I'm stuck after that. There are two fields (to start with) i want to pull, "Description" and "Features" as strings and fill their corresponding asp:TextBoxes.
I tried converting to array, and it still binds correctly, but it isn't indexing the fields, its viewed aa a single item of type Translation.
I tried an IEnumerable query and converting to a dataview but I got casting errors on the WHERE clause I couldn't resolve.
I tried this, but VS says 'myitem" is an unassigned local variable.
var query = from translation in Translations
where (Convert.ToString(translation.Name)) == itemname
select new { myitem = translation.Description, features = translation.Features };
ItemDescription.Text = myitem;
This seems like it should be a simple thing, am I just missing something here?

What's happening is you are getting an IEnumerable of an anonymous type with the properties of myitem and features.
You would need to change the last line to:
ItemDescription.Text = query.First().myitem;

Related

OpenUI Get List of Values

I am looking for a smart solution how to retrieve the Data from a LoV from a Business Component of Siebel. I tried to read the control with,...
var controls = this.GetPM().Get("GetControls");
for(var control in controls){
var value = this.GetPM().ExecuteMethod("GetFieldValue", controls[control]);
}
And with,...
this.GetPM().Get("GetRecordSet");
But the result for a LoV is still "". Is there a way without a Business Service to get the List of Values?
After a long search we got following answer,...
At the moment it is not possible. The problem is that the PM can only
see the active values of the Applet. The LoV (select in HTML) is
getting generated as soon the client clicks active on the select
element.
We build now a Business Service (BS) that provides the List of Values that i need to render.
Kind regards,
Myracle

Linq to SharePoint broken after converting columns to content types

We're working on a project that uses Linq to SharePoint. The list had several columns. After using SPMetal to make the class, it was imported into VS to access the data context. The Linq queries worked fine.
We went in a different direction, by deleting the list columns and using content types with site columns. OOTB, the add/edit forms work fine. But after updating the class with SPMetal and importing the class into VS for the data context, all the Linq query show as errors. Visual Studio cannot recognize the columns any longer because they don't appear to be there in the data context from the updated class. The columns are in the content types now, instead of the list.
Is there a way to get the content type's columns to export in the class file with SPMetal? Is there another library to import to write Linq to SharePoint queries with lists that have content types? How do you write Linq queries that use content type columns?
So say you have a list called Documents. It has two columns called 'One' and 'Two'. You make your Linq to SP queries just fine:
DataContext dc = new DataContext("http://sharepoint");
var varResults = (from item in dc.Documents
where item.Two == "blah"
orderby item.One descending
select item);
Then you decide you want to use content types with site columns. The above query breaks when you delete columns 'One' and 'Two' from the list. You make site columns and assign them to a content type called 'Master', parent being item. Master has two content types deriving from it called 'CloneA' and 'CloneB'. Since the clone content type's parent is Master, then they automatically get it's site columns. When you assign the content types to the list, the definition looks like:
Column - Content types
Title - Documents, Master, CloneA, CloneB
One - Master, CloneA, CloneB
Two - Master, CloneA, CloneB
The clone content types will later be used for different Information Policies for retention on the Documents list. After breaking the inheritance and setting up the retention policies on the content types, now items can individually set to a content type which will cause the retention (1 day - CloneA, 1 week - CloneB) to kick off.
But the linq to SP queries are still broken. Even though the site columns show up, SPMetal only captures the bases content type for some reason. So to linq, the columns are not really there with the above query. Typing "where item." the 'Two' doesn't even show up. You have to cast it to make it work (probably not explaining it right). So here's the working code:
DataContext dc = new DataContext("http://sharepoint");
var varResults = (from item in dc.Documents.OfType<Master>()
where item.Two == "blah"
orderby item.One descending
select item);
You may be tempted to use
var varResults = (from item in dc.Documents.OfType<DocumentsMaster>()
Unfortunately, that will only return the items that are associated with that content type in the list. So if you want to get items of a certain content type to filter, knock yourself out.

How to filter custom columns from SharePoint list using LINQ?

My requirement is to get items, only from custom-columns, in a SharePoint list using LINQ.
Since my custom columns are created dynamically based on some calculations done on another SPList, it keeps increasing and decreasing in the count frequently, therefore I cannot use SPMetal.
I need to include a condition (!(SPBuiltInFieldId.Contains(field.Id))) to check if the items are taken only from custom fields in the following query.
List<SPListItem> AllResponses = (from SPListItem Response in oList.Items
select Response).ToList();
Please advice. Thanks!
I'm not sure it's possible to have a list item that contains only custom columns. Even if Title is not there, you'll have ID, Modified, Created, etc. Plus, there will be a number of hidden built-in columns.
If you want a list of items that contain items with custom fields, you can try something like the following, which utilizes Where and Any methods:
List<SPListItem> AllResponses =
(from SPListItem Response in oList.Items select Response)
.Where(item => item.Fields
.Cast<SPField>()
.Any(field => !SPBuiltInFieldId.Contains(field.Id)))
.ToList();
This will return all items that have at least one custom field.

How can I get the IQueryable object used by LinqDataSource?

Is there a way to get the IQueryable object that the LinqDataSource has used to retrieve data? I thought that it might be possible from the selected event, but it doesn't appear to be.
Each row in my table has a category field, and I want to determine how many rows there are per category in the results.
I should also note that I'm using a DataPager, so not all of the rows are being returned. That's why I want to get the IQueryable, so that I can do something like
int count = query.Where(i => i.Category == "Category1").Count();
Use the QueryCreated event. QueryCreatedEventArgs has a Query property that contains the IQueryable.
The event is raised after the original LINQ query is created, and contains the query expression before to it is sent to the database, without the ordering and paging parameters.
There's no "Selected" event in IQueryable. Furthermore, if you're filtering your data on the server, there'd be no way you can access it, even if the API exposed it, but to answer a part of the question, let's say you have category -> product where each category has many products and you want the count of the products in each category. It'd be a simple LINQ query:
var query = GetListOfCategories();
var categoryCount = query.Select(c => c.Products).Count();
Again, depending on the type of object GetListOfCategories return, you might end up having correct value for all the entries, or just the ones that are loaded and are in memory, but that's the different between Linq-to-Objects (in memory) and Linq-to-other data sources (lazy loaded).

LINQ - NOT selecting certain fields?

I have a LINQ query mapped with the Entity Framework that looks something like this:
image = this.Context.ImageSet
.Where(n => n.ImageId == imageId)
.Where(n => n.Albums.IsPublic == true)
.Single();
This returns a single image object and works as intended.
However, this query returns all the properties of my Image table in the DB.
Under normal circumstances, this would be fine but these images contain a lot of binary data that takes a very long time to return.
Basically, in it current state my linq query is doing:
Select ImageId, Name, Data
From Images
...
But I need a query that does this instread:
Select ImageId, Name
From Images
...
Notice i want to load everything except the Data. (I can get this data on a second async pass)
Unfortunately, if using LINQ to SQL, there is no optimal solution.
You have 3 options:
You return the Entity, with Context tracking and all, in this case Image, with all fields
You choose your fields and return an anonymous type
You choose your fields and return a strongly typed custom class, but you lose tracking, if thats what you want.
I love LINQ to SQL, but thats the way it is.
My only solution for you would be to restructure your DataBase, and move all the large Data into a separate table, and link to it from the Image table.
This way when returning Image you'd only return a key in the new DataID field, and then you could access that heavier Data when and if you needed it.
cheers
This will create a new image with only those fields set. When you go back to get the Data for the images you select, I'd suggest going ahead and getting the full dataset instead of trying to merge it with the existing id/name data. The id/name fields are presumably small relative to the data and the code will be much simpler than trying to do the merge. Also, it may not be necessary to actually construct an Image object, using an anonymous type might suit your purposes just as well.
image = this.Context.ImageSet
.Where(n => n.ImageId == imageId)
.Where(n => n.Albums.IsPublic == true)
.Select( n => new Image { ImageId = n.ImageId, Name = n.Name }
.Single();
[If using Linq 2 SQL] Within the DBML designer, there is an option to make individual table columns delay-loaded. Set this to true for your large binary field. Then, that data is not loaded until it is actually used.
[Question for you all: Does anyone know if the entity frameworks support delayed loaded varbinary/varchar's in MSVS 2010? ]
Solution #2 (for entity framework or linq 2 sql):
Create a view of the table that includes only the primary key and the varchar(max)/varbinary(max). Map that into EF.
Within your Entity Framework designer, delete the varbinary(max)/varchar(max) property from the table definition (leaving it defined only in the view). This should exclude the field from read/write operations to that table, though you might verify that with the logger.
Generally you'll access the data through the table that excludes the data blob. When you need the blob, you load a row from the view. I'm not sure if you'll be able to write to the view, I'm not sure how you would do writes. You may be able to write to the view, or you may need to write a stored procedure, or you can bust out a DBML file for the one table.
You cannot do it with LINQ at least for now...
The best approach I know is create View for the table you need without large fields and use LINQ with that View.
Alternatively you could use the select new in the query expression...
var image =
(
from i in db.ImageSet
where i.ImageId == imageId && i.Albums.IsPublic
select new
{
ImageId = i.ImageId,
Name = i.Name
}
).Single()
The LINQ query expressions actually get converted to the Lambda expression at compile time, but I prefair using the query expression generally because i find it more readable and understandable.
Thanks :)

Resources