I have a rather complex database, where we are using Linq to SQL. I'm creating a model layer where I would like to only have one method. But my problem is that we often like to order the collection. Is it possible somehow to accomplish something like this:
public static List<Object> GetObject(Object.Property)
{
return some Linq.ToList();
}
I know I can use linq on my list afterwards.
Hmm it was maybe a bit to diffuse question.
OK I solved it with reflection and a string in the argument..
MyObjectDataDataContext context = new MyObjectDataDataContext ();
PropertyInfo[] piArray = context.MyObject.GetType().GetProperties();
PropertyInfo pi = piArray.FirstOrDefault(s => s.Name == "property");
if (pi != null)
{
return context.MyObject.OrderBy(t => pi.PropertyType);
}
I guess you are trying to access the same data, but depending on a 'column' criteria, return the data sorted?
Once you have the IEnumerable data, you can sort it as follows:
list.OrderBy(t => t.ColumnYouWantToSortBy)
As in the following documentation
Related
In C#, I'm going to use lambda expression, I have such a code
var item = dbContext.Products.ToList();
How can i get a property of Product table.
try this
var item = dbContext.Products.FirstOrDefault().Name;
With Lamba expression normally you can access and read information from "list" or in this case, IQueryable objects.
With your code you can access to objects with something like this:
var item = dbContext.Products.FirstOrDefault();
// item may be null if products table is empty
if (item != null)
{
// now you can access at object properties (example)
var data = item.PropertyData;
}
Your question may open others way that including reflection for exploring object without well known class definition...
If you want to get the property for each product with lambda expression, then you should make a lambda expression like x => x.Prop when you do your query
if (dbContext.Products != null){
var list = dbContext.Products.ToList();
var query = list.Select(x => x.Prop //your property will appear here...
}
I want to make a factory class to return DbContext object where table name will be passed as string. There are more than 100 tables in database, each having a different structure/schema.
The idea is to pass tableName as string in the method which will return object in EF and we can select/update these records. I found this code in some article but have some confusion how to use it:
public ObjectContext Context(EntityObject entity)
{
var relationshipManager = ((IEntityWithRelationships)entity).RelationshipManager;
var wrappedOwnerProperty = relationshipManager.GetType().GetProperty("WrappedOwner", BindingFlags.Instance | BindingFlags.NonPublic);
var wrappedOwner = wrappedOwnerProperty.GetValue(relationshipManager);
var contextProperty = wrappedOwner.GetType().GetProperty("Context");
return (ObjectContext)contextProperty.GetValue(wrappedOwner);
}
I am not sure if this is what I need. Also what should I pass in EntityObject entity and where I should pass the tableName?
Please let me know if there is any other way to achieve the same thing.
One simple way to do this is to use the DbContext.Set() method, and get the type based on the string.
using (var db = new MyDbContext)
{
string tableName = "ApplicationUser";
var type = Assembly.GetExecutingAssembly()
.GetTypes()
.FirstOrDefault(t => t.Name == tableName);
if(type != null)
DbSet catContext = context.Set(type);
}
However, this has one drawback and that's that this is a non-generic DbSet (ie it's a DbSet not a DbSet<T>).
A way to get the Generic DbSet (which allows linq functionality) would be to do something like this:
using (var db = new IdentityDbContext())
{
string tableName = "ApplicationUser";
var type = Assembly.GetExecutingAssembly()
.GetTypes().FirstOrDefault(t => t.Name == tableName);
var method = db.GetType().GetMethods()
.First(x => x.IsGenericMethod && x.Name == "Set");
MethodInfo generic = method.MakeGenericMethod(type);
var set = generic.Invoke(db, null);
}
Of course set will be an object here, and you'll have to cast it somehow, which is still part of the problem.
When it boils down to it, if you aren't going to work with statically compiled types, you're going to have to keep dealing with reflection, particularly when you have generic types to deal with (ie DbSet<T>, among others). You have to get them cast to a static type at some point to call the methods, or keep doing MethodInfo.Invoke's.
Another option is to use dynamic, but you can't use dynamics with c# extension methods (without casting to a concrete type) so you're back in the same boat of no Linq support.
Using Linq by reflection is a huge pain.
To be honest, If you have 100 classes, I'd just bite the bullet and write the hard coded types, or use a code generator to do it for you like CodeSmith.
Recently I asked a more general question about getting properties of model through foreign key.
Now I moved a bit further but still have no idea how transform objects on the fly.
What I've got is an IEnumerable collection which I get through repository
regionRaw = unitOfWork.RegionRepository.Get(
keyOrder: q => q.OrderBy(d => d.RegionID),
filter: p => p.FullName.Contains(lastname) || p.ShortName.Contains(lastname),
orderBy: jtSorting,
includeProperties: "District, ISO31662, GOST767Region");
Further I am going to export data from this collection to Excel. So I need a select statement that gets all the fields I need.
dt = regionRaw
.Select(x => new
{
ISO = x.ISO31662.GOSTName,
DistrictName = x.District.ShortName
})
I do not want to enumerate all the fields I need like on the top.
I am able to make a method that recognizes which of the fields have simple values and which have objects referenced through foreign key. And then that method will return a list of properties.
Now I need some way to write something like a foreach inside select. I see something like this:
dt = regionRaw
.Select(x => new
{
foreach (prop in propList)
{
prop.PropertyName = x.GetType()
.GetProperty(prop.TableName)
.GetValue(x, null).GetType()
.GetProperty(prop.PropertyName)
.GetValue(
x.GetType().GetProperty(prop.TableName).GetValue(x, null),
null);
}
}
Where propList is a collection of properties that I get before.
I do totally realize that upper code is more a pseudo-code but I have no idea how to realize this in .NET.
So if you can suggest some solution for this task I will be very grateful. Or maybe you could explain that all this is a bad idea and shouldn't be realized.
You wont be able to create an anonymous type with dynamic properties as anon types are created during compile and your properties are created during execution.
But why do you need strongly typed properties if you're not going to code against them, as you wont know them until someone executes the query?
Expando object may be of use to you?http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx
I've a LINQ query like below:
foreach (var property in from property in properties where property.Name != "Type" select property)
{
}
how would you go about making this statement more concise without using the actual extension method which looks unattractive (i.e. without using .Where like: foreach (var property in properties.Where(...)).
You cant really..
You could put the query into a separate line.
var selectedProperties = from property in properties
where property.Name != "Type"
select property;
foreach (var property in selectedProperties)
{
}
Or you could factor the query out into a separate method if it is really huge.
foreach ( var property in ComplexSelectionOfProperties () )
...
But really I would say the exention method in this case is much neater. Its only when the queries get more complex and involve joins that the query syntax becomes tidier. (IMHO)
Beauty is always in the eye of the beholder :)
However in such a case I would go create a method that filters non-Type properties and iterate over its results.
Something like this:
IEnumerable<IProperty> GetNonTypeProperties(IEnumerable<IProperty> properties)
{
return (from property in properties where property.Name != "Type" select property);
}
void foo()
{
foreach (var property in GetNonTypeProperties(properties))
{
}
}
The lack of conciseness comes precisely from the sql style syntax : using a "dot" notation you will sensibly shorten your expression :
foreach (var property in properties.Where(property => property.Name != "Type"))
{
}
If you want to shorten the longest part which is obviously the boolean test, you have to put it elsewhere.
Either in the foreach loop itself :
foreach (var property in properties)
{
if(property.Name != "Type")
{
...
}
}
Either if a separate function :
foreach (var property in properties.Where(IsNotType))
{
}
//and farther :
bool IsNotType(Property p)
{
return property.Name != "Type";
}
But anyway you want to perform a loop with a test on each element, so in a way or another you will have to code that and it will take a minimum amount of characters.
Just in case that you don't like the lambda expression, not the extension method itself, you can make your own extension method with query inside, like this:
public static IEnumerable<Property> PropertiesExceptType(this IEnumerable<Property> properties) {
return from property in properties
where property.Name != "Type"
select property;
}
and use it:
foreach(var property in properties.PropertiesExceptType()) {
// ...
}
The good thing about encapsulating your query in separate method is that you can debug the method with loop and change the code on the fly (VS won't let you do this if you have a linq query right inside this method).
I honestly don't see anything wrong with var propery in properties.Where(), it's much better than any query expression in this context IMO. But if you want to stick with your query, at least introduce a variable:
var filteredProperties = from property in properties
where property.Name != "Type"
select property;
foreach(var property in filteredProperties)
{
// ...
}
People who will read and debug it later will thank you. But I still think that extension method is the way to go here
What I'm trying to do is to pass an entity object to method and return all the names of the properties in it.
I'm using this code to get all the props names :
return classObject.GetType().GetProperties();
The problem is that this code return "EntityKey" and "EntityState" as properties whe I use it with Entity Object.
Is there any way to do it ?
Thanx in advance
You want all direct properties, but not the properties of the base type, which in your case is EntityObject:
var type = classObject.GetType();
//alternatively call out directly: typeof(EntityObject).GetProperties()...
var basePropertyNames = type.BaseType.GetProperties().Select(x => x.Name);
var props = type.GetProperties().Where(p => !basePropertyNames.Contains(p.Name));
This sample assumes there is a base type (which is the case for DB first), refactor when that is not guaranteed.
Edit from #Matt's comment: All of the above is unnecessary, could slap my head for not thinking of this - just use the right binding flags:
return classObject.GetType().GetProperties(BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance);
It is also possible without reflection:
using (var context = new ModelContainer())
{
// Access CSDL
var container = context.MetadataWorkspace
.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
// Access name of related set exposed on your context
var set = container.BaseEntitySets[context.YourEntitySet.EntitySet.Name];
// Access all properties
var properties = set.ElementType.Members.Select(m => m.Name).ToList();
// Access only keys
var keys = set.ElementType.KeyMembers.Select(m => m.Name).ToList();
}
As you can see you have access to much more then names. The example shows that you can now which property is part of key. If you access Members directly you can know which property is scalar, complex type or navigation property.
All information are already loaded so there is no need for reflection. If you want to use reflection don't forget to use it only once (first time you need it) and then store and reuse received property names. Reflection is slow so using it each time you need names is a bad practice.
I had the same problem. The solution I found was to create an array with the name of the properties to return (I olnly need a few). In your case, since it can be laborious to keep track of all properties, I would filter the properties EntityKey and EntityState and return all the others. The code would be something like this:
public IEnumerable<PropertyInfo> GetProperties()
{
Type t = this.GetType();
return t.GetProperties()
.Where(p => (p.Name != "EntityKey" && p.Name != "EntityState"))
.Select(p => p).ToList();
}
Don't know if there is a better solution, but it would be nice ;) Hope it helps!
As stated by BrokenGlass but beware if you need performance and you want to do this in loops. Reflection is not a fast thing.
If you need performance you may wish to put a virtual method in your base class to retrieve the properties as an array of strings or whatever, and override that in all derived classes. This would be the fastes approach but with more coding.