Confusion with DropDownListFor<> - asp.net-mvc-2

So what I am trying to do is import data from a database into a MVC2 DropDownListFor.
What I essentially have going is a roleplaying guild site I am working on for a friend. What the page should be doing is allowing a person to edit their character. So what is being passed into the page is the model containing the characters information. Then I have the view making a call to a method in the YourCharacterEdit model to get the information on a player character's race.
So I have tried to follow lots of different ideas that I have found from various tutorials online but nothing seems to be working. I am pretty much open to whatever ideas anyone might have at this point as to how I call fill up the drop down list. Currently I don't have much of a model to show because I keep scraping whatever I come up with.
The Controller:
if (Request.IsAuthenticated)
{
UserRepository _urepos = new UserRepository();
CharacterRepository _crepos = new CharacterRepository();
var check = _urepos.GetSpecificUserByName(User.Identity.Name);
var yourchar = _crepos.GetSpecificCharacter(CharID);
if (yourchar.CharUserRef == check.UserID)
{
//
YourCharacterEdit VarToReturn = new YourCharacterEdit();
VarToReturn.EmployeeID = yourchar.EmployeeID;
VarToReturn.CharFirstName = yourchar.CharFirstName;
VarToReturn.CharLastName = yourchar.CharLastName;
VarToReturn.CharGender = yourchar.CharGender;
VarToReturn.CharSpecies = yourchar.CharSpecies;
VarToReturn.CharDescription = yourchar.CharDescription;
VarToReturn.CharBackground = yourchar.CharBackground;
VarToReturn.CharJob = yourchar.CharJob;
return View("CharEdit", VarToReturn);
}
else
{
return View("401");
}
}
The View:
<div class="editor-field">
<%: Html.DropDownListFor(model => model.CharSpecies, ?)%>
<%: Html.ValidationMessageFor(model => model.CharSpecies) %>
</div>
So anyone have any good methods for getting the ListBox propagated?
Also the DB is access through guildEntities. The table is TBLCharS. The fields needed inside that table are CharS_id and CharS_name.

The first thing to do is define your model. The view should not need any additional data other than what you pass it in the model. Build your model and fill it up before calling the view.
My implementation is a bit overkill but here it goes:
In the model, create a container to hold the dropdown data:
public IEnumerable<SelectListItem> LocationList { get; set; }
In the controller, populate your model including the dropdown list:
model.LocationList = repository.GetLocationsSelectList(selectedLocationId);
I use a repository and Linq to grab the data from the database:
var q = (from l in Repository.For<LocationEntity>()
select new
{
RowId = l.RowId,
LocationString = l.Name,
});
var result = q.ToSelectList(a => a.RowId.ToString(), a => a.LocationString, a => a.RowId == locationId);
return result;
The ToSelectList extension I grabbed from somewhere (I forgot where):
public static class EnumerableExtensions
{
/// <summary>
/// Converts the source sequence into an IEnumerable of SelectListItem
/// </summary>
/// <param name="items">Source sequence</param>
/// <param name="nameSelector">Lambda that specifies the name for the SelectList items</param>
/// <param name="valueSelector">Lambda that specifies the value for the SelectList items</param>
/// <returns>IEnumerable of SelectListItem</returns>
public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector)
{
return items.ToSelectList(valueSelector, nameSelector, x => false);
}
/// <summary>
/// Converts the source sequence into an IEnumerable of SelectListItem
/// </summary>
/// <param name="items">Source sequence</param>
/// <param name="nameSelector">Lambda that specifies the name for the SelectList items</param>
/// <param name="valueSelector">Lambda that specifies the value for the SelectList items</param>
/// <param name="selectedItems">Those items that should be selected</param>
/// <returns>IEnumerable of SelectListItem</returns>
public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector, IEnumerable<TValue> selectedItems)
{
return items.ToSelectList(valueSelector, nameSelector, x => selectedItems != null && selectedItems.Contains(valueSelector(x)));
}
/// <summary>
/// Converts the source sequence into an IEnumerable of SelectListItem
/// </summary>
/// <param name="items">Source sequence</param>
/// <param name="nameSelector">Lambda that specifies the name for the SelectList items</param>
/// <param name="valueSelector">Lambda that specifies the value for the SelectList items</param>
/// <param name="selectedValueSelector">Lambda that specifies whether the item should be selected</param>
/// <returns>IEnumerable of SelectListItem</returns>
public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector, Func<TItem, bool> selectedValueSelector)
{
foreach (var item in items)
{
var value = valueSelector(item);
yield return new SelectListItem
{
Text = nameSelector(item),
Value = value.ToString(),
Selected = selectedValueSelector(item)
};
}
}
}
And finally, in your view:
<%: Html.LabelFor(m => m.LocationId)%>
<%: Html.DropDownListFor(m => m.LocationId, Model.LocationList, "<-- Select One -->")%>
<%: Html.ValidationMessageFor(m => m.LocationId)%>
Add a comment if you have any questions or need more code.

Related

OpenXML - Apply bookmarks to paragraph in word document

Below code works fine using OPENXML (asp.net) and print us elements in word document with HEADING2... how can we apply bookmark to specific paragraph..
What we r trying is extract sections between two HEADINGs...We are wondering how to apply bookmark and how can we use that extract text between two bookmarks...
const string fileName = #"D:\DocFiles\Scan.docx";
const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
const string stylesRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
XNamespace w = wordmlNamespace;
XDocument xDoc = null;
XDocument styleDoc = null;
using (Package wdPackage = Package.Open(fileName, FileMode.Open, FileAccess.Read))
{
PackageRelationship docPackageRelationship =
wdPackage
.GetRelationshipsByType(documentRelationshipType)
.FirstOrDefault();
if (docPackageRelationship != null)
{
Uri documentUri =
PackUriHelper
.ResolvePartUri(
new Uri("/", UriKind.Relative),
docPackageRelationship.TargetUri);
PackagePart documentPart =
wdPackage.GetPart(documentUri);
// Load the document XML in the part into an XDocument instance.
xDoc = XDocument.Load(XmlReader.Create(documentPart.GetStream()));
// Find the styles part. There will only be one.
PackageRelationship styleRelation =
documentPart.GetRelationshipsByType(stylesRelationshipType)
.FirstOrDefault();
if (styleRelation != null)
{
Uri styleUri = PackUriHelper.ResolvePartUri(documentUri, styleRelation.TargetUri);
PackagePart stylePart = wdPackage.GetPart(styleUri);
// Load the style XML in the part into an XDocument instance.
styleDoc = XDocument.Load(XmlReader.Create(stylePart.GetStream()));
}
}
}
string defaultStyle =
(string)(
from style in styleDoc.Root.Elements(w + "style")
where (string)style.Attribute(w + "type") == "paragraph" &&
(string)style.Attribute(w + "default") == "1"
select style
).First().Attribute(w + "styleId");
// Find all paragraphs in the document.
var paragraphs =
from para in xDoc
.Root
.Element(w + "body")
.Descendants(w + "p")
let styleNode = para
.Elements(w + "pPr")
.Elements(w + "pStyle")
.FirstOrDefault()
select new
{
ParagraphNode = para,
StyleName = styleNode != null ?
(string)styleNode.Attribute(w + "val") :
defaultStyle
};
// Retrieve the text of each paragraph.
var paraWithText =
from para in paragraphs
select new
{
ParagraphNode = para.ParagraphNode,
StyleName = para.StyleName,
Text = ParagraphText(para.ParagraphNode)
};
foreach (var p in paraWithText)
{
if (p.StyleName=="Heading2")
{
Response.Write(p.StyleName + " -" + p.Text);
Response.Write("</br>");
}
}
Here's a sample Bookmark class that I created to demonstrate how you can deal with bookmarks. It finds pairs of w:bookmarkStart and w:bookmarkEnd elements and shows how you can get hold of the w:r elements between those two markers. Based on that, you can process the text, e.g., as shown in the GetValue() method.
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using OpenXmlPowerTools;
namespace CodeSnippets.OpenXml.Wordprocessing
{
/// <summary>
/// Represents a corresponding pair of w:bookmarkStart and w:bookmarkEnd elements.
/// </summary>
public class Bookmark
{
private Bookmark(XElement root, string bookmarkName)
{
Root = root;
BookmarkStart = new XElement(W.bookmarkStart,
new XAttribute(W.id, -1),
new XAttribute(W.name, bookmarkName));
BookmarkEnd = new XElement(W.bookmarkEnd,
new XAttribute(W.id, -1));
}
private Bookmark(XElement root, XElement bookmarkStart, XElement bookmarkEnd)
{
Root = root;
BookmarkStart = bookmarkStart;
BookmarkEnd = bookmarkEnd;
}
/// <summary>
/// The root element containing both <see cref="BookmarkStart"/> and
/// <see cref="BookmarkEnd"/>.
/// </summary>
public XElement Root { get; }
/// <summary>
/// The w:bookmarkStart element.
/// </summary>
public XElement BookmarkStart { get; }
/// <summary>
/// The w:bookmarkEnd element.
/// </summary>
public XElement BookmarkEnd { get; }
/// <summary>
/// Finds a pair of w:bookmarkStart and w:bookmarkEnd elements in the given
/// <paramref name="root"/> element, where the w:name attribute value of the
/// w:bookmarkStart element is equal to <paramref name="bookmarkName"/>.
/// </summary>
/// <param name="root">The root <see cref="XElement"/>.</param>
/// <param name="bookmarkName">The bookmark name.</param>
/// <returns>A new <see cref="Bookmark"/> instance representing the bookmark.</returns>
public static Bookmark Find(XElement root, string bookmarkName)
{
XElement bookmarkStart = root
.Descendants(W.bookmarkStart)
.FirstOrDefault(e => (string) e.Attribute(W.name) == bookmarkName);
string id = bookmarkStart?.Attribute(W.id)?.Value;
if (id == null) return new Bookmark(root, bookmarkName);
XElement bookmarkEnd = root
.Descendants(W.bookmarkEnd)
.FirstOrDefault(e => (string) e.Attribute(W.id) == id);
return bookmarkEnd != null
? new Bookmark(root, bookmarkStart, bookmarkEnd)
: new Bookmark(root, bookmarkName);
}
/// <summary>
/// Gets all w:r elements between the bookmark's w:bookmarkStart and
/// w:bookmarkEnd elements.
/// </summary>
/// <returns>A collection of w:r elements.</returns>
public IEnumerable<XElement> GetRuns()
{
return Root
.Descendants()
.SkipWhile(d => d != BookmarkStart)
.Skip(1)
.TakeWhile(d => d != BookmarkEnd)
.Where(d => d.Name == W.r);
}
/// <summary>
/// Gets the concatenated inner text of all runs between the bookmark's
/// w:bookmarkStart and w:bookmarkEnd elements, ignoring paragraph marks
/// and page breaks.
/// </summary>
/// <remarks>
/// The output of this method can be compared to the output of the
/// <see cref="XElement.Value"/> property.
/// </remarks>
/// <returns>The concatenated inner text.</returns>
public string GetValue()
{
return GetRuns().Select(UnicodeMapper.RunToString).StringConcatenate();
}
}
}
The above class processes documents like the following (very simple test document):
<?xml version="1.0" encoding="utf-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:t>First</w:t>
</w:r>
</w:p>
<w:bookmarkStart w:id="1" w:name="_Bm001" />
<w:p>
<w:r>
<w:t>Second</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t>Third</w:t>
</w:r>
</w:p>
<w:bookmarkEnd w:id="1" />
<w:p>
<w:r>
<w:t>Fourth</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
The above document is created by the following unit tests, which demonstrate how you could use the Bookmark class:
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using CodeSnippets.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using OpenXmlPowerTools;
using Xunit;
namespace CodeSnippets.Tests.OpenXml.Wordprocessing
{
public class BookmarkTests
{
/// <summary>
/// The w:name value of our bookmark.
/// </summary>
private const string BookmarkName = "_Bm001";
/// <summary>
/// The w:id value of our bookmark.
/// </summary>
private const int BookmarkId = 1;
/// <summary>
/// The test w:document with our bookmark, which encloses the two runs
/// with inner texts "Second" and "Third".
/// </summary>
private static readonly XElement Document =
new XElement(W.document,
new XAttribute(XNamespace.Xmlns + "w", W.w.NamespaceName),
new XElement(W.body,
new XElement(W.p,
new XElement(W.r,
new XElement(W.t, "First"))),
new XElement(W.bookmarkStart,
new XAttribute(W.id, BookmarkId),
new XAttribute(W.name, BookmarkName)),
new XElement(W.p,
new XElement(W.r,
new XElement(W.t, "Second"))),
new XElement(W.p,
new XElement(W.r,
new XElement(W.t, "Third"))),
new XElement(W.bookmarkEnd,
new XAttribute(W.id, BookmarkId)),
new XElement(W.p,
new XElement(W.r,
new XElement(W.t, "Fourth")))
)
);
/// <summary>
/// Creates a <see cref="WordprocessingDocument"/> for on a <see cref="MemoryStream"/>
/// testing purposes, using the given <paramref name="document"/> as the w:document
/// root element of the main document part.
/// </summary>
/// <param name="document">The w:document root element.</param>
/// <returns>The <see cref="MemoryStream"/> containing the <see cref="WordprocessingDocument"/>.</returns>
private static MemoryStream CreateWordprocessingDocument(XElement document)
{
var stream = new MemoryStream();
const WordprocessingDocumentType type = WordprocessingDocumentType.Document;
using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(stream, type))
{
MainDocumentPart part = wordDocument.AddMainDocumentPart();
part.PutXDocument(new XDocument(document));
}
return stream;
}
[Fact]
public void GetRuns_WordprocessingDocumentWithBookmarks_CorrectRunsReturned()
{
// Arrange.
// Create a new Word document on a Stream, using the test w:document
// as the main document part.
Stream stream = CreateWordprocessingDocument(Document);
// Open the WordprocessingDocument on the Stream, using the Open XML SDK.
using WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true);
// Get the w:document element from the main document part and find
// our bookmark.
XElement document = wordDocument.MainDocumentPart.GetXElement();
Bookmark bookmark = Bookmark.Find(document, BookmarkName);
// Act, getting the bookmarked runs.
IEnumerable<XElement> runs = bookmark.GetRuns();
// Assert.
Assert.Equal(new[] {"Second", "Third"}, runs.Select(run => run.Value));
}
[Fact]
public void GetText_WordprocessingDocumentWithBookmarks_CorrectRunsReturned()
{
// Arrange.
// Create a new Word document on a Stream, using the test w:document
// as the main document part.
Stream stream = CreateWordprocessingDocument(Document);
// Open the WordprocessingDocument on the Stream, using the Open XML SDK.
using WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true);
// Get the w:document element from the main document part and find
// our bookmark.
XElement document = wordDocument.MainDocumentPart.GetXElement();
Bookmark bookmark = Bookmark.Find(document, BookmarkName);
// Act, getting the concatenated text contents of the bookmarked runs.
string text = bookmark.GetValue();
// Assert.
Assert.Equal("SecondThird", text);
}
}
}
You can find the full code example in my CodeSnippets GitHub repository. Look for the Bookmark and BookmarkTests classes and note that I'm using the Open-Xml-PowerTools.
You can obviously do more complicated things with those Open XML elements. This is just a simple example.

Difference between Set() and RaisePropertyChanged()

I am reading this http://msdn.microsoft.com/en-us/magazine/jj651572.aspx to learn mvvm light framework.
I download the source code Friend.cs.
My question is why some set method of different property are implemented differently.
For example, the setter for First name is, why I need 'ref' keyword for _firstName.
Set(FirstNamePropertyName, ref _firstName, value);
And the setter for DateOfBirthString is "
RaisePropertyChanged(() => DateOfBirth);
When will the linq expression will be evaluated?
namespace MyFriends.Model
{
[SimpleSerialize]
public class Friend : ObservableObject
{
/// <summary>
/// The <see cref="FirstName" /> property's name.
/// </summary>
public const string FirstNamePropertyName = "FirstName";
private string _firstName;
/// <summary>
/// Sets and gets the FirstName property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "first_name")]
public string FirstName
{
get
{
return _firstName;
}
set
{
Set(FirstNamePropertyName, ref _firstName, value);
}
}
/// <summary>
/// The <see cref="LastName" /> property's name.
/// </summary>
public const string LastNamePropertyName = "LastName";
private string _lastName;
/// <summary>
/// Sets and gets the LastName property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "last_name")]
public string LastName
{
get
{
return _lastName;
}
set
{
Set(LastNamePropertyName, ref _lastName, value);
}
}
/// <summary>
/// The <see cref="DateOfBirth" /> property's name.
/// </summary>
public const string DateOfBirthPropertyName = "DateOfBirth";
private string _dateOfBirthString;
/// <summary>
/// Sets and gets the DateOfBirth property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[SimpleSerialize(FieldName = "birthday")]
public string DateOfBirthString
{
get
{
return _dateOfBirthString;
}
set
{
_dateOfBirthString = value;
RaisePropertyChanged(() => DateOfBirth);
}
}
public DateTime DateOfBirth
{
get
{
if (string.IsNullOrEmpty(_dateOfBirthString))
{
return DateTime.MinValue;
}
return DateTime.ParseExact(DateOfBirthString, "d", CultureInfo.InvariantCulture);
}
set
{
_dateOfBirthString = value.ToString("d", CultureInfo.InvariantCulture);
}
}
private string _imageUrl;
[SimpleSerialize(FieldName = "picture")]
public string ImageUrl
{
get
{
return _imageUrl;
}
set
{
_imageUrl = value;
RaisePropertyChanged(() => ImageUri);
}
}
public Uri ImageUri
{
get
{
return new Uri(_imageUrl);
}
}
}
}
The difference between those two methods is that the Set method replaces the old value of the _firstName field and then raises the PropertyChanged event, while the RaisePropertyChanged only raises the PropertyChanged event.
You'll want to use the Set method in most cases, since it helps to shorten property declarations by wrapping all that typically needs to be done within a property's setter in just one method:
It updates the value of the passed field and overwrites it with the content of value, and then
raises the PropertyChanged event to notify Views about this update.
The reason the field needs to be passed by reference (thus using ref _firstName) is that not the field's content is needed within the Set method, but the field itself is actually updated.
The RaisePropertyChanged method is useful when an update of one property does also affect additional properties. In this case, these properties' contents need to be updated manually, then the RaisePropertyChanged method can be called to inform Views about which properties have actually changed.
One instance I found that Set(ref _prop, value)
doesn't work is when you need to resend an update or need to do a custom comparison. Set(ref _prop, value)
will do a compare on the _prop and value for you but it may not be what you want. For some properties i may want to add some more conditions beyond just a comparison in which case I'll set the _prop = value manually and then raise the change right after;
But in most cases I use the Set(ref _prop, value)
Here is an actual usage, where the IsRunning is the primary operation, but it also raises a change notification on the property IsComplete which is based on IsRunning. This way both properties send a notify without undo extra coding.
private bool _IsRunning;
public bool IsRunning
{
get => _IsRunning;
set
{
SetProperty(ref _IsRunning, value);
RaisePropertyChanged("IsComplete");
}
}
public bool IsComplete => !IsRunning;

Handling ProgressBar's Value change with UIAutomation

How can I be notified when ProgressBar's Value changes with .NET UIAutomation framework? I dont see such property in AutomationElement class.
I drew this sample directly from the MSDN documentation, changing only the property:
AutomationPropertyChangedEventHandler propChangeHandler;
/// <summary>
/// Adds a handler for property-changed event; in particular, a change in the value
/// </summary>
/// <param name="element">The UI Automation element whose state is being monitored.</param>
public void SubscribePropertyChange(AutomationElement element)
{
Automation.AddAutomationPropertyChangedEventHandler(element,
TreeScope.Element,
propChangeHandler = new AutomationPropertyChangedEventHandler(OnPropertyChange),
ValuePattern.ValueProperty);
}
/// <summary>
/// Handler for property changes.
/// </summary>
/// <param name="src">The source whose properties changed.</param>
/// <param name="e">Event arguments.</param>
private void OnPropertyChange(object src, AutomationPropertyChangedEventArgs e)
{
AutomationElement sourceElement = src as AutomationElement;
if (e.Property == ValuePattern.ValueProperty)
{
// TODO: Do something with the new value.
// The element that raised the event can be identified by its runtime ID property.
}
else
{
// TODO: Handle other property-changed events.
}
}
public void UnsubscribePropertyChange(AutomationElement element)
{
if (propChangeHandler != null)
{
Automation.RemoveAutomationPropertyChangedEventHandler(element, propChangeHandler);
}
}

How do I get the old values of an entity?

How do I get the old values of an entity?
follows the example..
public void Update(User user)
ValidateEntity(user, OperationType.Update);
oldUser = (how do I get the old values ​​(database) of the entity User?)
Set.Attach(user);
Context.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
Context.SaveChanges();
OnUpdated(user, oldUser);
}
Try this:
public void Update(User user)
ValidateEntity(user, OperationType.Update);
var oldUser = Set.Single(u => u.Id == user.Id);
Context.Detach(oldUser);
Set.Attach(user);
Context.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
Context.SaveChanges();
OnUpdated(user, oldUser);
}
Or this:
public void Update(User user)
{
ValidateEntity(user, OperationType.Update);
var oldUser = Set.Single(u => u.Id == user.Id);
Set.ApplyCurrentValues(user);
Context.SaveChanges(SaveOptions.DetectChangesBeforeSave);
OnUpdated(user, Context.ObjectStateManager.GetOjectStateEntry(user).OriginalValues);
Context.AcceptAllChanges();
}
I found one way of convert DbDataRecord to entity type using reflection...
where http://www.instanceofanobject.com/2011/01/ef4-dbdatarecord-convertto.html
public static class AnonymousTypeConversion
{
///
/// Converts a single DbDataRwcord object into something else.
/// The destination type must have a default constructor.
///
///
///
///
public static T ConvertTo(this DbDataRecord record)
{
T item = Activator.CreateInstance();
for (int f = 0; f
/// Converts a list of DbDataRecord to a list of something else.
///
///
///
///
public static List ConvertTo(this List list)
{
List result = (List)Activator.CreateInstance>();
list.ForEach(rec =>
{
result.Add(rec.ConvertTo());
});
return result;
}
}

Ado.net entity .include() method not working

I've got this function
public static AdoEntity.Inspector GetInspectorWithInclude(int id, List<string> properties)
{
using (var context = new Inspection09Entities())
{
var query = context.Inspector;
if (properties != null)
{
foreach (var prop in properties)
{
if (!string.IsNullOrEmpty(prop))
query.Include(prop);
}
}
return query.Where(i => i.ID == id).First();
}
}
which i use to get my "Inspectors" from the DB and an additional feature to specify what to "Include" with the data. So it takes a List<'string'> and includes them with the query. This function doesn't seem to work because the returned object still does not include the requested data. Could someone tell me what is wrong with this method/approach.
Thanks in advance.
Solution
Thank you to Misha N. suggestion, I have hatched this EF helper which extends the ObjectQuery class. Hopefully others may find it useful.
/// <summary>
/// The include extesion that takes a list and returns a object query with the included data.
/// </summary>
/// <param name="objectQuery">
/// The object query.
/// </param>
/// <param name="includes">
/// The list of strings to include.
/// </param>
/// <typeparam name="T">
/// </typeparam>
/// <returns>
/// An object query of T type with the included data.
/// </returns>
public static ObjectQuery<T> Include<T>(this ObjectQuery<T> objectQuery, List<string> includes)
{
ObjectQuery<T> query = objectQuery;
if (includes != null) includes.ForEach(s => { if (!string.IsNullOrEmpty(s)) query = query.Include(s); });
return query;
}
Usage example.
using(var context = new MyEntity())
{
var includes = new List<string>
{
"Address",
"Orders",
"Invoices"
}
return context.CustomerSet.Include(includes).First(c => c.ID == customerID);
}
Nothing is wrong with your approach, just one little thing need to be changed:
public static AdoEntity.Inspector GetInspectorWithInclude(int id, List<string> properties)
{
using (var context = new Inspection09Entities())
{
var query = context.Inspector;
if (properties != null)
{
foreach (var prop in properties)
{
if (!string.IsNullOrEmpty(prop))
query = query.Include(prop);// <--- HERE
}
}
return query.Where(i => i.ID == id).First();
}
}
ObjectQuery.Include() method is returning altered ObjectQuery object, you haven't been doing changes to the inital query.
Hope this helps