Can't get items from DDS via query LINQ - c#

I am new to C# ASP.NET and I am trying to get the items from a store (EPiServer).
Visual Studio says
Cannot resolve symbol Where, OnderzoekId and ToList
What am I doing wrong? I used this code example:
[EPiServerDataStore(AutomaticallyCreateStore = true, AutomaticallyRemapStore = true)]
public class OnderzoekColumn
{
private static int Counter = 0;
public Identity Id { get; set; }
public int ColumnId { get; set; }
public int OnderzoekId { get; set; }
public string ColumnName { get; set; }
public OnderzoekColumn()
{
Initialize();
}
public OnderzoekColumn(int onderzoekId, string columnName)
{
Initialize();
OnderzoekId = onderzoekId;
ColumnName = columnName;
}
protected void Initialize()
{
Id = Identity.NewIdentity(Guid.NewGuid());
ColumnId = System.Threading.Interlocked.Increment(ref Counter);
OnderzoekId = 0;
ColumnName = string.Empty;
}
public static List<OnderzoekColumn> GetOnderzoekColumns(int onderzoekId)
{
var store = typeof(OnderzoekColumn).GetStore();
var columns = from c in store
where c.OnderzoekId == onderzoekId
select c;
if (columns == null)
{
return new List<OnderzoekColumn>();
}
return columns.ToList<OnderzoekColumn>();
}
}

The linq statement
var columns = from c in store
where c.OnderzoekId == onderzoekId
select c;
is trying to enumerate over a collection, but the GetStore() method returns a single item. Try using the following code in place of your GetOnderzoekColumns method (its untested)
public static List<OnderzoekColumn> GetOnderzoekColumns(int onderzoekId)
{
var store = typeof(OnderzoekColumn).GetStore();
var columns = store.Items<OnderzoekColumn>().Where(c => c.OnderzoekId == onderzoekId);
return columns.ToList();
}
I'd add the following extension methods to your solution, then you can use a strongly typed Find method, which will be more efficient than the above, which returns all items, then filters in memory using the linq Where() method.

I used the following code to get it to work. I removed the AutomaticallyCreateStore and AutomaticallyRemapStore attribute also.
public static List<OnderzoekColumn> GetOnderzoekColumns(int onderzoekId)
{
var store = DynamicDataStoreFactory.Instance.GetStore(typeof(OnderzoekColumn));
var query = from item in store.Items<OnderzoekColumn>()
where item.OnderzoekId == onderzoekId
select item;
return query.ToList();
}

Related

Join sub variables in a List

I have my variables class with constructor
public class Gdf2Lines
{
public string line { get; set; }
public int linenumber { get; set; }
public string columnNumber { get; set; }
public string columnName { get; set; }
public Gdf2Lines()
{
line = "";
linenumber = -1;
columnNumber = ""; // prefer to keep as the string read from the text source
columnName = "";
}
}
I have my class that creates of list of the above class and populates the variables within for each line from a file
class GDF2
{
Gdf2Lines Data = new Gdf2Lines();
List<Gdf2Lines> gdf2 = new List<Gdf2Lines>();
public GDF2(string[] arrFile)
{
int count = 0;
foreach (String line in arrFile)
{
Data.line = line;
Data.linenumber = count;
Data.columnNumber = GetColumnNumber(line);
Data.columnName = GetColumnName(line);
count++;
gdf2.Add(Data);
}
}
}
I know a "normal" list can be joined into a string by:
String.Join(Environment.Newline.ToString(), List);
But is there an equally easy way to join one of the (sub) variables within my list, such as
String.Join(",", gdf2.columnName);
Currently I am using a for loop.
Something like this should work:
String.Join(",", gdf2.Select(x => x.columnName));
This uses LINQ to extract a list of columnName values from the list of Gdf2Line.

Select columns from table based on column names from another table

At the beginning I am aware that there are similar questions, but mine is a little bit different.
I implemented a function that allows the user to select the columns he wants to see.
I've created a stored procedure that gets all column names from the UserColumns table, creates a dynamic sql query and then runs the exec (#command) query. The functionality described above works very well, but there are more requirements that I can't handle this way.
There is TasksViewModel:
public class TasksViewModel
{
public List<Dictionary<List<string>, List<List<object>>>> Tasks { get; set; }
public List<UserDefaultStatusesViewModel> UserStatuses { get; set; }
public List<ZgloszenieStatus> TaskStatuses { get; set; }
public TasksViewModel()
{
}
}
Tasks is filled by stored procedure that runs SELECT x,y,z... FROM table... query.
I'm using this method:
private static IEnumerable<Dictionary<List<string>, List<List<object>>>> Read(DbDataReader reader)
{
var dict = new Dictionary<List<string>, List<List<object>>>();
var cols = new List<string>();
for (int temp = 0; temp < reader.FieldCount; temp++)
{
cols.Add(reader.GetName(temp));
}
var items = new List<List<object>>();
while (reader.Read())
{
var tmp = new List<object>();
for (int i = 0; i < reader.FieldCount; i++)
{
tmp.Add(reader.GetValue(i));
}
items.Add(tmp);
}
dict.Add(cols, items);
foreach (var item in dict)
{
}
yield return dict;
}
I find this very overcomplicated, but at the moment I have no idea if there is another way to do this.
I'm using Entity Framework in my application.
Imagine that I'm using List<Tasks> instead of List<Dictionary<List<string>, List<List<object>>>>. Tasks is database table.
public class Tasks
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime Date { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
User wants to see only ID,Title,Description columns, so the UserColumns table looks like this:
UserId | ColumnName
1 | ID
2 | Title
3 | Description
Is there a way to select specific columns from List<Tasks> based on UserColumns table using Entity Framework ?
You can create the lambda for Column List dynamically
static Func<Tasks, Tasks> CreateSelect(string[] columns)
{
var parameterExpression = Expression.Parameter(typeof(Tasks), "p");
var newExpression = Expression.New(typeof(Tasks));
var bindings = columns.Select(o => o.Trim())
.Select(o =>
{
var pi = typeof(Tasks).GetProperty(o);
var memberExpression = Expression.Property(parameterExpression, pi);
return Expression.Bind(pi, memberExpression);
}
);
var memberInitExpression = Expression.MemberInit(newExpression, bindings);
var lambda = Expression.Lambda<Func<Tasks, Tasks>>(memberInitExpression, parameterExpression);
return lambda.Compile();
}
and create a LINQ query based on that lambda (columnNameList array is rows from UserColumns table)
static void Foo()
{
var columnNameList = new string[] { "ID", "Title", "Description" };
var tasksList = new List<Tasks>
{
new Tasks{ ID=1, Title="T1", FirstName="F1", LastName="L1", Description="D1", Date=DateTime.UtcNow },
new Tasks{ ID=2, Title="T2", FirstName="F2", LastName="L2", Description="D2", Date=DateTime.UtcNow }
};
var tasks = tasksList.Select(CreateSelect(columnNameList)).FirstOrDefault();
}
I hope that answers your question.

Trouble getting MemberName of "Name" from CustomAttributes = ColumnAttribute of Linq Table Class

I have a little algo I wrote to compare the Linq DataContext table to the sql table. It rolls through the properties of the Linq table and gets the CustomeAttributes of the property, (table columns). It's been working for years, but somebody created a table field with a # sign in it, (UPS#). Linq doesn't like such a name for its properties for obvious reasons. So, it has a member of the ColumnAttribute called "Name" to handle the swap. But, I've always used the "Storage" member for my column name. You would think you would just pick up the "Name" member if it's present, but I can't find it to save my life.
This is the code. Any help is very much appreciated.
public static ColumnInfo[] GetColumnsInfo(Type linqTableClass)
{
// Just looking in the loop to see if I missed something.
foreach (var fld in linqTableClass.GetProperties())
{
foreach (var attr in fld.CustomAttributes)
{
foreach (var arg in attr.NamedArguments)
{
if (arg.MemberName == "Name")
Debug.WriteLine(arg.MemberName);
Debug.WriteLine("{0}", arg.MemberName);
}
}
}
var columnInfoQuery =
from field in linqTableClass.GetProperties()
from attribute in field.CustomAttributes
from namedArgument in attribute.NamedArguments
where namedArgument.MemberName == "DbType"
select new ColumnInfo
{
//ColumnName = field.Name,
ColumnName = namedArgument.MemberName,
DatabaseType = namedArgument.TypedValue.Value.ToString(),
};
return columnInfoQuery.ToArray();
}
and this is the property in the Table Class:
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="PEER_UPS#", Storage="_PEER_UPS_", DbType="Char(31) NOT NULL", CanBeNull=false)]
public string PEER_UPS_
{
get
{
return this._PEER_UPS_;
}
set
{
if ((this._PEER_UPS_ != value))
{
this.OnPEER_UPS_Changing(value);
this.SendPropertyChanging();
this._PEER_UPS_ = value;
this.SendPropertyChanged("PEER_UPS_");
this.OnPEER_UPS_Changed();
}
}
}
I couldn't find a pretty way to get this done. For some reason the ColumnAttribute just didn't want to play nice. Ugly as this is, it works.
public class ColumnInfo
{
public string ColumnName { get; set; }
public string DatabaseType { get; set; }
}
public static IEnumerable<ColumnInfo> GetColumnsInfo(Type linqTableClass)
{
Debug.WriteLine(string.Format("Table: {0}", linqTableClass.Name));
/// In-Case this has to grow in the future. Using a list for the arg names to search for.
/// The primary arg should be in position 0 of the array.
string dbTypeArgName = "DbType";
string fldPrimayName = "Storage";
string fldSecondaryName = "Name";
List<string> fldArgnames = new List<string>() { fldPrimayName, fldSecondaryName };
foreach (var fld in linqTableClass.GetProperties())
{
Debug.WriteLine(string.Format("Field Name: {0}", fld.Name));
foreach (var attr in fld.GetCustomAttributesData().Cast<CustomAttributeData>()
.Where(r => r.AttributeType == typeof(ColumnAttribute))
.Where(a => a.NamedArguments
.Select(n => n.MemberName)
.Intersect(fldArgnames)
.Any()))
{
var fldName = attr.NamedArguments.Where(r => r.MemberName == fldSecondaryName).Count() != 0
? attr.NamedArguments.Where(r => r.MemberName == fldSecondaryName).SingleOrDefault().TypedValue.Value.ToString()
: fld.Name;
var fldType = attr.NamedArguments
.Where(r => r.MemberName == dbTypeArgName)
.Select(r => r.TypedValue.Value.ToString())
.SingleOrDefault();
Debug.WriteLine(string.Format("\tTable Field Name {0} Table Type {1}", fldName, fldType));
yield return new ColumnInfo()
{
ColumnName = fldName,
DatabaseType = fldType,
};
}
}
}
and here is what i suggest:
[sorry, my first example was indeed too simplistic]
Here is how i'd do it:
namespace LinqAttributes
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
public class ColumnInfo
{
public string ColumnName { get; set; }
public string DatabaseType { get; set; }
}
public class Test
{
[System.Data.Linq.Mapping.ColumnAttribute(Name = "Whatever", Storage = "Whatever", DbType = "Char(20)", CanBeNull = true)]
public string MyProperty { get; set; }
[System.Data.Linq.Mapping.ColumnAttribute(Name = "PEER_UPS#", Storage = "_PEER_UPS_", DbType = "Char(31) NOT NULL", CanBeNull = false)]
public string PEER_UPS_ { get; set; }
}
internal class Program
{
public static IEnumerable<ColumnInfo> GetColumnsInfo(Type type)
{
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(type))
{
var columnAttribute = descriptor.Attributes
.OfType<System.Data.Linq.Mapping.ColumnAttribute>().SingleOrDefault();
if (columnAttribute != null)
{
yield return new ColumnInfo
{
ColumnName = columnAttribute.Name,
DatabaseType = columnAttribute.DbType
};
}
}
}
private static void Main(string[] args)
{
foreach (var item in GetColumnsInfo(typeof(Test)))
{
Debug.WriteLine(item.ColumnName);
}
}
}
}
Just tested it.
Cheers!
public class City
{
public City() { }
[Column("id_city")]
public int Id { get; private set; }
}
var obj = new City();
var pro = obj.GetType().GetProperties();
string columnAttribute = pro.GetCustomAttributes<ColumnAttribute>().FirstOrDefault().Name;
if(columnAttribute == "id_city") {
//sucess
}

Distinct Value from Linq Query

I have the below class and linq query I am using to populate a grid!
The Title is the same for every row returned. What I am trying to do is populate mString with the distinct Title from the query so I can bind it to a seperate textblock.
I probably didnt need to show all the code, but maybe it will help. How can I show the distinct Title.
public class Items
{
public int Id { get; set; }
public string Details { get; set; }
public string Title { get; set; }
public int NewNumber { get; set; }
}
private ObservableCollection<Items> mItem = new ObservableCollection<Items>();
private string mString = string.Empty;
public string SpecTitle
{
get { return mString; }
}
public ObservableCollection<Items> GetItems
{
get { return mItem; }
}
Here is the linq query
var results = (from z in mContext.View
orderby z.ItemNumber ascending
where z.ItemId == mId
select new Items()
{
Id = z.ItemId,
Details = z.Details,
Title = z.ItemTitle,
NewNumber = z.ItemNumber
});
List<Items> mNewItems = results.ToList();
mItem.Clear();
mNewItems.ForEach(y => mItem.Add(y));
var titleList = mNewItems.Select(i => i.Title).Distinct().ToList();
Converting my comment into an answer:
just do Items.Select(x => x.Title).Distinct();.
There is an additional library called moreLinq https://code.google.com/p/morelinq/ that has an extenction distinctby that you can you to distinct based on the given key.
it would as simle as this
var results = (from z in mContext.View
orderby z.ItemNumber ascending
where z.ItemId == mId
select new Items()
{
Id = z.ItemId,
Details = z.Details,
Title = z.ItemTitle,
NewNumber = z.ItemNumber
}).DistinctBy(c=>c.Title).ToList();
You can implement your custom comparer for distinct:
public class ItemsComparer : IEqualityComparer<Items>
{
public bool Equals(Items x, Items y)
{
return x.Title == y.Title;
}
public int GetHashCode(Items obj)
{
return obj.Title.GetHashCode();
}
}
then just use
var titleList = mNewItems.Distinct(new ItemsComparer()).Select(t=>t.Items);

Distinct with custom comparer

Trying to use Distinct() using a custom comparer and it gives me the error:
cannot be inferred from the usage. Try specifying the type arguments explicitly
The Default comparer works fine but doesn't give the results I expect of course. How can I fix this?
public class TimeEntryValidation
{
public string EmployeeID { get; set; }
public string EmployeeLocation { get; set; }
public string EmployeeDepartment { get; set; }
public int RowIndex { get; set; }
}
public class MyRowComparer : IEqualityComparer<TimeEntryValidation>
{
public bool Equals(TimeEntryValidation x, TimeEntryValidation y)
{
return (x.EmployeeDepartment == y.EmployeeDepartment && x.EmployeeLocation == y.EmployeeLocation);
}
public int GetHashCode(TimeEntryValidation obj)
{
return obj.EmployeeID.GetHashCode();
}
}
void Query(List<TimeEntryValidation> listToQuery)
{
var groupedData =
from oneValid in listToQuery
group oneValid by oneValid.EmployeeID
into g
where g.Count() > 1
select new {DoubleItems = g};
var listItems = groupedData.Distinct(new MyRowComparer());
}
The type of groupedData is some IEnumerable<{an anonymous type}> whereas MyRowComparer is IEqualityComparer<TimeEntryValidation>
It's unclear whether you intended listItems to be a list of groups, or whether you wanted the actual items themselves.
If it's the latter, you probably want something like this:
void Query(List<TimeEntryValidation> listToQuery)
{
var groupedData = from oneValid in listToQuery
group oneValid by oneValid.EmployeeID
into g
where g.Count() > 1
select g ;
var listItems = groupedData.SelectMany(group => group).Distinct(new MyRowComparer());
//listItems is now an IEnumerable<TimeEntryValidation>
}

Categories

Resources