question about linq select and ToList() - c#

I have a problem with returning a list by executing a Select LINQ query. This is the query:
var data = Repository<EducationString>
.Find()
.ToList()
.Select(p => new EducationStringModel() {
Id = p.Id,
Title = p.Title,
EducationDegree=p.EducationDegree })
.ToList();
As you can see I used ToList() 2 times. I don't know why but when I delete the first ToList() I see this error, "Index was outside the bounds of the array", but by having both ToList() there is no problem.
Would it help if I said EducationDegree in EducationStringModel is an IList<EducationDegree>?
Is there anybody who knows the reason?
#Mark :its L2O
if u need to see the classes:
public class EducationStringModel
{
private IList _educationDegree = new List();
public IList EducationDegree
{
get
{
if (_educationDegree == null)
{
_educationDegree = new List();
}
return _educationDegree;
}
set { _educationDegree = value; }
}
public int? Id { get; set; }
public string Title { get; set; }
}
public class EducationString{
private string _title;
private IList _educationExperiences;
private IList _educationDegree;
virtual public string Title
{
get { return _title; }
set { _title = value; }
}
virtual public IList<EducationExperience> EducationExperiences
{
get
{
if (_educationExperiences == null)
{
_educationExperiences = new List<EducationExperience>();
}
return _educationExperiences;
}
set
{
_educationExperiences = value;
}
}
virtual public IList<EducationDegree> EducationDegree
{
get
{
if (_educationDegree == null)
{
_educationDegree = new List<EducationDegree>();
}
return _educationDegree;
}
set
{
_educationDegree = value;
}
}
}

Is that the actual code? The only unclear thing there is: what does Find() return?
It sounds like the ToList is helping here by breaking composition and using LINQ-to-Objects, in which case AsEnumerable() should work just as well. After that you just do a Select (which for L2O just takes each item in turn and applies the map). If Find() is something more exotic, it sounds like a bug in that LINQ provider (or perhaps more fairly: that provider struggling to cope with an atypical construct). Hard to say more without a fully reproducible example.

Related

EF CF - List<T> of Primitive Type

I have the following:
public class Broadcast {
public int NumUsersToMessage { get; set; }
public int NumMessagesQueued { get; set; }
public string DbUsersMessaged { get; set; }
public int NumMessagesSent {
get {
return UsersMessaged.Count();
}
}
public List<int> UsersMessaged {
get {
return DbUsersMessaged == null ? new List<int>() : DbUsersMessaged.Split(',').Select(Int32.Parse).ToList();
}
set {
DbUsersMessaged = value != null ? String.Join(",", value) : null;
}
}
}
My goal here is to only ever access DbUsersMessaged through UsersMessaged. I'm attempting to do broadcast.UsersMessaged.Add(2), however since this is not an assignment, I can't get the property to behave as I like. Instead, I have to do this:
tempList = broadcast.UsersMessaged();
tempList.Add(2);
broadcast.UsersMessaged = tempList;
db.SaveChanges();
Which is obviously unwieldy. I'm considering making an AddReassign extension method but I want to know - what's the standard practice here for supporting Lists of primitive types? It looks like even with the extension method, my best shot looks like this:
broadcast.UsersMessaged = broadcast.UsersMessaged.AddReassign(2) // yuck!
Before anyone asks - we've intentionally denormalized this for performance reasons.
If you don't care about performance, you can create own list:
public class MyList : IList<int>
{
private List<int> underlyingList;
private Broadcast entity;
public MyList(Broadcast entity)
{
this.entity = entity;
this.underlyingList = entity.DbUsersMessaged?.Split(",") ?? new List<int>();
}
public void Add(int i)
{
this.underlyingList.Add(i);
this.entity.DbUsersMessaged = String.Join(",", underylingList);
}
// other interface memebers impl
}
Then
MyList list;
public IList<int> UsersMessaged {
get {
return myList ?? (myList = new MyList(this));
}
}
Of course it is only sample.
I recommend you to have a look at this: Entity Framework 5 - Looking for Central Point to Execute Custom Code after Entity is Loaded from Database
And then convert from string to list, and then use Saving Changes event to convert back into the string construction when saving.
Then, for performance, maybe you want to use byte[] rather than a string for storing the data in the database.

C# Find Index of a List of Classes

Finding an Index of a Class:
The only way I know to find an index of List is
int index = listEmployee.FindIndex(
delegate(Employee findEmployee)
{
return findEmployee.Name.Equals(findName, StringComparison.Ordinal);
});
I was wondering how to add the option to use
int indexT = listEmployee.FindIndex(r >= r.Name == findName);
Or basically what I'm doing wrong that I can't use it.
class Employee
{
private string _name; private int _idNumber;
private string _deptarment; private string _position;
public Employee()
{
_name = ""; _idNumber = 0; _deptarment = ""; _position = "";
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public int IdNumber
{
get { return _idNumber; }
set { _idNumber = value; }
}
public string Department
{
get { return _deptarment; }
set { _deptarment = value; }
}
public string Position
{
get { return _position; }
set { _position = value; }
}
}
I was wondering how to add the option to use
int indexT = listEmployee.FindIndex(r >= r.Name == findName);
That's fine, apart from the syntax problem at r >= which should be r =>
So this works:
int indexT = listEmployee.FindIndex(r => r.Name == findName);
See: Lambda Expressions
int indexT = listEmployee.FindIndex(r => r.Name == findName);
should work. Perhaps you are missing the using System.Linq referece
Not entirely sure what you're trying to accomplish, but a simple List collection is not going to ensure order or sort, so the index (especially if the collection is going to be expected to change) is not a reliable means of accessing a specific object.
If index / order is important, maybe look at a different collection type, such as the Sorted list: http://msdn.microsoft.com/en-us/library/system.collections.sortedlist.aspx
If you're just trying to find a specific object, you can use Linq and just go something like:
listEmployee.Where( r => r.Name == findName );

storing Linq To Entities query in new object projection

I have a Linq to Entities query and I want to select some specific columns and store the new object into a pre-defined object. However, I'm getting the error
<object> does not contain a constructor that takes 0 arguments.
Not sure what is wrong here...
Also not sure if this is the best way or if using anonymous type is better instead of creating a payroll object.
Linq Query
public Payroll GetTestCasePayroll(decimal testScenarioID) //not sure if object is correct return
{
Payroll instance = (from o in DbContext.UI_OnDemandCheckHeader
where o.TestScenarioID == testScenarioID
select new Payroll(o.PayEntityCode, o.PayrollYear, o.PayrollNumber)).First();
//{ PayEntityCode = , PayrollYear = o.PayrollYear, PayrollNumber = o.PayrollNumber }).First();
return instance;
}
Payroll object
class Payroll
{
private string _payEntityCode;
private decimal _payrollYear;
private string _payrollNumber;
public Payroll(string payEntityCode, decimal payrollYear, string payrollNumber)
{
PayEntityCode = payEntityCode;
PayrollYear = payrollYear;
PayrollNumber = payrollNumber;
}
public decimal PayrollYear
{
get { return _payrollYear; }
set { _payrollYear = value; }
}
public string PayEntityCode
{
get { return _payEntityCode; }
set { _payEntityCode = value; }
}
public string PayrollNumber
{
get { return _payrollNumber; }
set { _payrollNumber = value; }
}
Your Payroll class needs a constructor that takes no parameters e.g.
Public Payroll() { }
Linq works by creating an empty instance of the output class and then using the setters on each of the properties. It does not use anything but an empty constructor.

Mapping POCO to string in Linq to Sql so that I can use Linq on my POCO

I'm accessing a database column where a phone number is stored as a varchar in the format +a-b:c where a = country code, b = phone number and c = extension. E.g. +44-07700123456:123
So I have a type that handles serialization along the lines of:
public struct PhoneNumber {
public PhoneNumber(string val) { /*...*/ }
public override string ToString() { /*...*/ }
public static PhoneNumber TryParse(string val) { /*...*/ }
}
and a POCO:
public class Customer {
public PhoneNumber? HomePhone;
}
Then in my data access code some Linq along the lines of:
public IQueryable<Customers> GetCustomers() {
var customers = (from c in DataContext.Customers
select new Customer {
HomePhone = PhoneNumber.TryParse(c.HomePhone)
});
return customers;
}
So far so good, this all works fine when retrieving records from the database, but my problem is I can't perform a Linq query on the result like:
GetCustomers().Where(c => c != null && c.HomePhone.Value.ToString().Contains("123"));
I get a an error "Method 'System.Nullable`1[PhoneNumber] TryParse(System.String)' has no supported translation to SQL". Now I know I can perform the phone number search in GetCustomers() but this is not ideal.
Is there a way I can let Linq know how to translate my linq to sql? So that I can I do something like GetCustomers().Where(c => c.HomePhone.Value.ToString().Contains("123")) ?
P.S. Not sure on the title of this one, any alternatives are welcome.
The problem is that your PhoneNumber.TryParse() call is getting translated into an expression that's sent up to the server, which it doesn't understand. Furthermore, there's no way to tell SQL about your structure so you won't be able to do a server-side query based on the parsed value. One option is to capture the string value and move the PhoneNumber.TryParse() bit somewhere else. For example:
public class Customer {
public string HomePhoneString;
private bool _HomePhoneParsed;
private PhoneNumber? _HomePhone;
public PhoneNumber? HomePhone
{
get
{
if(!_HomePhoneParsed)
{
_HomePhone = PhoneNumber.TryParse(HomePhoneString);
_HomePhoneParsed = true;
}
return _HomePhone;
}
}
}
public IQueryable<Customers> GetCustomers() {
var customers = (from c in DataContext.Customers
select new Customer {
HomePhoneString = c.HomePhone
});
return customers;
}
And then you can either query server-side:
GetCustomers().Where(c => c.HomePhoneString != null && c.HomePhoneString.Contains("123"))
Or client-side:
GetCustomers().AsEnumerable()
.Where(c => c.HomePhone != null && c.HomePhone.Value.Contains("123"))
Following up on this, an alternative solution is to change PhoneNumber to a class and add a 'Value' property to serialize/deserialize like:
public class PhoneNumber {
public override string ToString() { /*...*/ }
public Parse(string val) { /*...*/ }
public string Value {
get {
return ToString();
}
set {
Parse(value);
}
}
}
This kind of code is not really suitable for a property but it does allow you to initialize the HomePhone object in the Linq query like:
var customers = (from c in DataContext.Customers
select new Customer {
FirstName = c.FirstName,
HomePhone = new PhoneNumber {
Value = c.HomePhone
}
});
Which then means you can use the serializer like:
customers.Where(x => x.HomePhone.Value.Contains("123"));

How to design collection in C#

I have a class MySet
class MySet
{
.......
}
This class will declare a reference to another type
(i.e)
class MySubSet
{
....
}
The purpose of the type MySubset is to supply "subset id" and a collection of integers to
the type MySet.
Which one of the followings is the correct implementation
(1)
class MySet
{
int mySetID;
MySubSet subset = new MySubSet();
public int MySetID
{
get { return mySetID; }
set { mySetID = value; }
}
public MySubSet MySubSet
{
get { return subset; }
set { subset = value; }
}
}
class MySubSet
{
int subsetID;
List<int> subset = new List<int>();
public List<int> SubSet
{
get { return subset; }
set { subset = value; }
}
public int SubSetID
{
get { return subsetID; }
set { subsetID = value; }
}
}
(2)
class MySet
{
int mySetID;
AnotherSubSet subset = new AnotherSubSet();
public int MySetID
{
get { return mySetID; }
set { mySetID = value; }
}
public AnotherSubSet MySubSet
{
get { return subset; }
set { subset = value; }
}
}
class AnotherSubSet : List<int>
{
int subsetID;
List<int> lst = new List<int>();
public int SubSetID
{
get { return subsetID; }
set { subsetID = value; }
}
}
If both are worst design consideration help me to implement the one that I could follow.
MySet doesn't look like a collection to me. It's just a class.
I'd rename it to ´MyEntity´or something like that.
List<MyEntity> mySet = new List<MyEntity>();
From all the information you've provided, I would do this:
public class MyEntity
{
public int ID { get; set; } // shortcut
public List<int> Numbers = new List<int> { get; set; } // shortcut
}
Sorry, I don't have /Net3.0 to hand so can't check the constructor of the list with the shortcut get/set but its the theory that counts...
The first version is better (as improved upon by ck) - use composition instead of inheritance. You are advised not to add properties to collections, which is effectively what you're doing in version 2. Collections should contain their items only. Someone else may be able to expand on the reasons for this, as I am not an expert, but it does cause serialization problems.
Number 2 is better, use inheritence not composition for this pattern, - because fundementally, it is a collection. It does not contain a collection. Inheritance gives you all the functionality of the base class without the need to write pass-through functions. If you want to add a new item to the collection, using composition, you either have to add a pass through method for the Add() method to class MySubSet:
class MySubSet
{
int subsetID;
List<int> subset = new List<int>();
public List<int> SubSet
{
get { return subset; }
set { subset = value; }
}
public void Add(int i) { subset.Add(i); } // pass through to subset.Add()
}
or you have to use the following non-intuitive and confusing syntax...
MySet.MySubSet.SubSet.Add(67);
with inheritence, all you need is
MySet.MySubSet.Add(67);

Categories

Resources