I am trying to write this code in a more generic fashion:Is it possible that based on T i can use the right entityframework entity? So for example if I would use :
public IQueryable<T> GetCount(string filterExpression)
{
//return db.Persons.Where("it." + filterExpression);
return db. ? .Where("it." + filterExpression); // depending on type T
}
UPDATE
so now I did this:
public int GetCount<T>(string filter)
where T : class
{
NortwindEntities db = new NortwindEntities();
return db.CreateObjectSet<T>().Where(filter).Count();
}
error:
Error 2 The constraints for type parameter 'T' of method 'MyBase<T>.GetCount<T>(string)' must match the constraints for type parameter 'T' of interface method 'MyBase<T>.GetCount<T>(string)'. Consider using an explicit interface implementation instead
Are you sure that you want a queryable of T? (the name of your method is GetCount.)
You can do this to get a IQueryable<T> from your DbContext.
public IQueryable<T> GetCount<T>(Func<T, bool> predicate)
where T : class
{
MyContext db = new MyContext();
return db.Set<T>().Where(predicate).AsQueryable();
}
IQueryable<Person> result = GetCount<Person>(x => x.Id == 1);
I suggest to use the name Where as your method name.
public IQueryable<T> Where<T>(Func<T, bool> predicate)
where T : class
{
MyContext db = new MyContext();
return db.Set<T>().Where(predicate).AsQueryable();
}
IQueryable<Person> result = Where<Person>(x => x.Id == 1);
Update
Decorate the method with where T : class if you get the following exception.
The type 'T' must be a reference type in order to use it as parameter 'TEntity' in the generic type or method ?
Update 2
Seems that you really only want the count.
public int GetCount<T>(Func<T, bool> predicate)
where T : class
{
MyContext db = new MyContext();
return db.Set<T>().Where(predicate).Count();
}
int count = GetCount<Person>(x => x.Id == 1);
Related
How do I configure the mapper so that this works?
(i.e. the properties from the dynamic object should map to the properties of the class definition with the same letters - ignoring case)
public class Foo {
public int Bar { get; set; }
public int Baz { get; set; }
}
dynamic fooDyn = new MyDynamicObject();
fooDyn.baR = 5;
fooDyn.bAz = 6;
Mapper.Initialize(cfg => {});
Foo result = Mapper.Map<Foo>(fooDyn);
result.Bar.ShouldEqual(5);
result.Baz.ShouldEqual(6);
If your dynamic object implements IDictionary<string,object> (e.g. ExpandoObject) then the following should work. There must be some easier way to do this as anonymous objects are mapped just fine even if the case is different.
Mapper.Initialize(cfg =>
{
cfg.CreateMap<IDictionary<string, object>, Foo>()
.ConstructUsing(d =>
{
Foo foo = new Foo();
foreach (System.Reflection.PropertyInfo prop in typeof(Foo).GetProperties())
{
foreach (KeyValuePair<string, object> entry in d)
{
if (entry.Key.ToLowerInvariant() == prop.Name.ToLowerInvariant())
{
prop.SetValue(foo, entry.Value);
break;
}
}
}
return foo;
});
});
AutoMapper allows you to configure explicit member mapping on the map configuration in this style:
var config = new MapperConfiguration(cfg =>
{
var dynamicMap = cfg.CreateMap<IDictionary<string, object>, SomethingDTO>();
dynamicMap.ForAllMembers((expression) => expression.MapFrom(source =>
source.ContainsKey(expression.DestinationMember.Name.Substring(0, 1).ToLower()
+ expression.DestinationMember.Name.Substring(1))
? source[expression.DestinationMember.Name.Substring(0, 1).ToLower()
+ expression.DestinationMember.Name.Substring(1)] : null
));
});
For mapping a dynamic/expando object that is camel case to an type with pascal case members you could use ForAllMembers on the the explicit map configuration. Possible use case: json payloads to DTO.
In comparison to the other answer (which also works) this approach allows you to continue to benefit and use all the other map features and configuration.
I need generic way to filter IQueryable data and filters are populated as dictionary. I have already created method like this.
public static IEnumerable<T> CustomApplyFilter<T>(this IQueryable<T> source, Dictionary<string, string> filterBy)
{
foreach (var key in filterBy.Keys)
{
source.Where(m => m.GetType().GetProperty(key).GetValue(m, null).Equals(filterBy[key]));
}
return source.ToList();
}
But its always returning same result.
please find the caller
Dictionary<string, string> dtFilter = new Dictionary<string, string>();
dtFilter.Add("Id", "2");
var res = context.Set<MyEntity>().CustomApplyFilter<MyEntity>(dtFilter);
The Where extension method does not change the content of the IQueryable it is applied to. The return value of the method should be used:
public static IEnumerable<T> CustomApplyFilter<T>(this IQueryable<T> source, Dictionary<string, string> filterBy)
{
foreach (var key in filterBy.Keys)
{
source = source.Where(m => m.GetType().GetProperty(key).GetValue(m, null).Equals(filterBy[key]));
}
return source.ToList();
}
UPDATE:
I should have noticed it, my answer so far was applicable to LINQ to Objects only. When using LINQ to Entities, however, there are certain restrictions; only expression that can be converted to an SQL query can be used. Getting properties through reflection is not such an expression obviously.
When this is the case, one possible solution would be to build the ExpressionTree manually.
public static IEnumerable<T> CustomApplyFilter<T>(this IQueryable<T> source, Dictionary<string, string> filterBy)
{
foreach (var key in filterBy.Keys)
{
var paramExpr = Expression.Parameter(typeof(T), key);
var keyPropExpr = Expression.Property(paramExpr, key);
var eqExpr = Expression.Equal(keyPropExpr, Expression.Constant(filterBy[key]));
var condExpr = Expression.Lambda<Func<T, bool>>(eqExpr, paramExpr);
source = source.Where(condExpr);
}
return source.ToList();
}
UPDATE2:
With the comment #Venkatesh Kumar given below, it is apparent that when the underlying type of the field provided is not of type string, this solution fails (with the error message : The binary operator Equal is not defined for the types 'System.Int64' and 'System.String').
One possible way to tackle this problem would be to have a dictionary of types and delegates to use for each such property.
Since this is a static method (an extension method which has to be static), declaring a static Dictionary in class scope would be reasonable:
Let's assume the name of the class in which CustomApplyFilter is declared is SOFExtensions:
internal static class SOFExtensions
{
private static Dictionary<Type, Func<string, object>> lookup = new Dictionary<Type, Func<string, object>>();
static SOFExtensions()
{
lookup.Add(typeof(string), x => { return x; });
lookup.Add(typeof(long), x => { return long.Parse(x); });
lookup.Add(typeof(int), x => { return int.Parse(x); });
lookup.Add(typeof(double), x => { return double.Parse(x); });
}
public static IEnumerable<T> CustomApplyFilter<T>(this IQueryable<T> source, Dictionary<string, string> filterBy)
{
foreach (var key in filterBy.Keys)
{
var paramExpr = Expression.Parameter(typeof(T), key);
var keyPropExpr = Expression.Property(paramExpr, key);
if (!lookup.ContainsKey(keyPropExpr.Type))
throw new Exception("Unknown type : " + keyPropExpr.Type.ToString());
var typeDelegate = lookup[keyPropExpr.Type];
var constantExp = typeDelegate(filterBy[key]);
var eqExpr = Expression.Equal(keyPropExpr, Expression.Constant(constantExp));
var condExpr = Expression.Lambda<Func<T, bool>>(eqExpr, paramExpr);
source = source.Where(condExpr);
}
return source.ToList();
}
}
Other types and proper delegates for them should be added to the lookup Dictionary as required.
I am trying to dynamically create a class instance based type using generics, however I am encountering difficulty with class introspection.
Here are the questions:
Is there a Swift-equivalent to Obj-C's self.class?
Is there a way to instantiate a class using the AnyClass result from NSClassFromString?
Is there a way to get AnyClass or otherwise type information strictly from a generic parameter T? (Similar to C#'s typeof(T) syntax)
Well, for one, the Swift equivalent of [NSString class] is .self (see Metatype docs, though they're pretty thin).
In fact, NSString.class doesn't even work! You have to use NSString.self.
let s = NSString.self
var str = s()
str = "asdf"
Similarly, with a swift class I tried...
class MyClass {
}
let MyClassRef = MyClass.self
// ERROR :(
let my_obj = MyClassRef()
Hmm… the error says:
Playground execution failed: error: :16:1: error: constructing an object of class type 'X' with a metatype value requires an '#required' initializer
Y().me()
^
<REPL>:3:7: note: selected implicit initializer with type '()'
class X {
^
It took me a while to figure out what this means… turns out it wants the class to have a #required init()
class X {
func me() {
println("asdf")
}
required init () {
}
}
let Y = X.self
// prints "asdf"
Y().me()
Some of the docs refer to this as .Type, but MyClass.Type gives me an error in the playground.
Here's how to use NSClassFromString. You have to know the superclass of what you're going to end up with. Here are a superclass-subclass pair that know how to describe themselves for println:
#objc(Zilk) class Zilk : NSObject {
override var description : String {return "I am a Zilk"}
}
#objc(Zork) class Zork : Zilk {
override var description : String {return "I am a Zork"}
}
Notice the use of the special #obj syntax to dictate the Objective-C munged name of these classes; that's crucial, because otherwise we don't know the munged string that designates each class.
Now we can use NSClassFromString to make the Zork class or the Zilk class, because we know we can type it as an NSObject and not crash later:
let aClass = NSClassFromString("Zork") as NSObject.Type
let anObject = aClass()
println(anObject) // "I am a Zork"
And it's reversible; println(NSStringFromClass(anObject.dynamicType)) also works.
Modern version:
if let aClass = NSClassFromString("Zork") as? NSObject.Type {
let anObject = aClass.init()
print(anObject) // "I am a Zork"
print(NSStringFromClass(type(of:anObject))) // Zork
}
If I'm reading the documentation right, if you deal with instances and e.g. want to return a new instance of the same Type than the object you have been given and the Type can be constructed with an init() you can do:
let typeOfObject = aGivenObject.dynamicType
var freshInstance = typeOfObject()
I quickly tested it with String:
let someType = "Fooo".dynamicType
let emptyString = someType()
let threeString = someType("Three")
which worked fine.
In swift 3
object.dynamicType
is deprecated.
Instead use:
type(of:object)
Swift implementation of comparing types
protocol Decoratable{}
class A:Decoratable{}
class B:Decoratable{}
let object:AnyObject = A()
object.dynamicType is A.Type//true
object.dynamicType is B.Type//false
object.dynamicType is Decoratable.Type//true
NOTE: Notice that it also works with protocols the object may or may not extend
Finally got something to work. Its a bit lazy but even the NSClassFromString() route did not work for me...
import Foundation
var classMap = Dictionary<String, AnyObject>()
func mapClass(name: String, constructor: AnyObject) -> ()
{
classMap[name] = constructor;
}
class Factory
{
class func create(className: String) -> AnyObject?
{
var something : AnyObject?
var template : FactoryObject? = classMap[className] as? FactoryObject
if (template)
{
let somethingElse : FactoryObject = template!.dynamicType()
return somethingElse
}
return nil
}
}
import ObjectiveC
class FactoryObject : NSObject
{
#required init() {}
//...
}
class Foo : FactoryObject
{
class override func initialize()
{
mapClass("LocalData", LocalData())
}
init () { super.init() }
}
var makeFoo : AnyObject? = Factory.create("Foo")
and bingo, "makeFoo" contains a Foo instance.
The downside is your classes must derrive from FactoryObject and they MUST have the Obj-C +initialize method so your class gets automagically inserted in the class map by global function "mapClass".
Here is another example showing class hierarchy implementation, similar to accepted answer, updated for the first release of Swift.
class NamedItem : NSObject {
func display() {
println("display")
}
required override init() {
super.init()
println("base")
}
}
class File : NamedItem {
required init() {
super.init()
println("folder")
}
}
class Folder : NamedItem {
required init() {
super.init()
println("file")
}
}
let y = Folder.self
y().display()
let z = File.self
z().display()
Prints this result:
base
file
display
base
folder
display
Well, I have the following scenario:
public class Joins<TOuter, TInner, TResult>
{
public Expression<Func<TOuter, object>> outerKeySelector;
public Expression<Func<TInner, object>> innerKeySelector;
public Expression<Func<TOuter, TInner, object>> resultSelector;
public IEnumerable<TResult> r;
}
public class Test<T>
{
public IEnumerable<TResult> Join<TInner, TResult>(
Expression<Func<T, object>> outerKeySelector,
Expression<Func<TInner, object>> innerKeySelector,
Expression<Func<T, TInner, TResult>> resultSelector) where TInner : class
{
var join = new Joins<T, TInner, TResult>();
join.innerKeySelector = innerKeySelector;
join.outerKeySelector = outerKeySelector;
return join.r;
}
}
To create the join method, I relied on the link: http://msdn.microsoft.com/en-us/library/bb534644(v=vs.100).aspx
However, when I try to invoke the method, TInner is not recognized, making the method becomes invalid me returning the following error:
Cannot convert expression type 'type' to return type 'TResult'
Note: The class 'Joins' is purely a test, none of it is definitive and the var 'r' is for testing only, used only to facilitate the return.
Example of intended use:
var test = new Test<User>().Join<Permission>(u => u.Id, p => p.IdUser, (u, p) => new { Id = u.Id , Area = p.Area });
More details:
As mentioned, TInner is not recognized, so I can not make a call the correct method.
As a test I did so:
var test = new Test<User>().Join<Permission>(u => u.Id, p => p.ToString(), (u, p) => new {Id = u.Id, Name = p.ToString()});
I know p.ToString() is not correct, but is not recognizing the properties of the class indicated (in the case Permission), then put ToString() just to finish writing the method.
EDIT:
I need to use the result in a foreach/for
example:
foreach(var obj in test)
{
var id = obj.Id;
var area = obj.Area;
.
.
.
}
To make it work, you should do the following:
var test = new Test<User>().Join<Permission, object>(u => u.Id, p => p.IdUser, (u, p) => new { Id = u.Id, Area = p.Area });
// ^^ (resolve the second type argument as well)
When you define the following:
public TResult Join<TInner, TResult>
then you should either give compiler a hint which type there will be (instead of any, mentioned as type argument: TInner, TResult) explicitly, or it must be somehow recognized automatically by compiler (and then you can ommit it from explicit definition), but in your case you must do that explicitly.
Have a look of this answer. Even though that question is also related to extension methods, there is a pretty good explanation of the logic with the type arguments to resolve.
EDIT:
But object, for sure, is not the best decision, as you can not do anything with that object later (especially, if that's an anonymous type).
So, you should change it, for instance, in the following way:
public class Test<T, TInner> where TInner : class where T : class
{
public IEnumerable<TResult> Join<TResult>(
...
Expression<Func<T, TInner, TResult>> resultSelector)
after that you can use it as follows:
var test = new Test<User, Permission>()
.Join(u => u.Id, p => p.IdUser, (u, p) => new { Id = u.Id, Area = p.Area });
EDIT:
if you need the TInner and TResult to be passed to Join method, that's not really possible. The anonymous class can be resolved only automatically by compiler - you can not specify it explicitly.
So, the only way you can solve it then, as the following:
var test = new Test<User>().Join<Permission, dynamic>(...
that would allow you to use your result then with LinQ .Where( method, however, without intellisense support (unless, you create a concrete class for the Join output).
Using Entity Framework I can create concrete classes from most of the sprocs in the database of a project I'm working on. However, some of the sprocs use dynamic SQL and as such no metadata is returned for the sproc.
So for a that sproc, I manually created a concrete class and now want to map the sproc output to this class and return a list of this type.
Using the following method I can get a collection of objects:
var results = connection.Query<object>("get_buddies",
new { RecsPerPage = 100,
RecCount = 0,
PageNumber = 0,
OrderBy = "LastestLogin",
ProfileID = profileID,
ASC = 1},
commandType: CommandType.StoredProcedure);
My concrete class contains
[DataContractAttribute(IsReference=true)]
[Serializable()]
public partial class LoggedInMember : ComplexObject
{
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Int16 RowID
{
get
{
return _RowID;
}
set
{
OnRowIDChanging(value);
ReportPropertyChanging("RowID");
_RowID = StructuralObject.SetValidValue(value);
ReportPropertyChanged("RowID");
OnRowIDChanged();
}
}
private global::System.Int16 _RowID;
partial void OnRowIDChanging(global::System.Int16 value);
partial void OnRowIDChanged();
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.String NickName
{
get
{
return _NickName;
}
set
{
OnNickNameChanging(value);
ReportPropertyChanging("NickName");
_NickName = StructuralObject.SetValidValue(value, false);
ReportPropertyChanged("NickName");
OnNickNameChanged();
}
}
private global::System.String _NickName;
partial void OnNickNameChanging(global::System.String value);
partial void OnNickNameChanged();
.
.
.
Without having to iterate through the results and add the output parameters to the LoggedInMember object, how do I map these on the fly so I can return a list of them through a WCF service?
If I try var results = connection.Query<LoggedInMember>("sq_mobile_get_buddies_v35", ... I get the following error:
System.Data.DataException: Error parsing column 0 (RowID=1 - Int64)
---> System.InvalidCastException: Specified cast is not valid. at Deserialize...
At a guess your SQL column is a bigint (i.e. Int64 a.k.a. long) but your .Net type has a n Int16 property.
You could play around with the conversion and ignore the stored procedure by doing something like:
var results = connection.Query<LoggedInMember>("select cast(9 as smallint) [RowID] ...");
Where you are just selecting the properties and types you want to return your object. (smallint is the SQL equivalent of Int16)
The solution to this was to create a complex object derived from the sproc with EF:
public ProfileDetailsByID_Result GetAllProfileDetailsByID(int profileID)
{
using (IDbConnection connection = OpenConnection("PrimaryDBConnectionString"))
{
try
{
var profile = connection.Query<ProfileDetailsByID_Result>("sproc_profile_get_by_id",
new { profileid = profileID },
commandType: CommandType.StoredProcedure).FirstOrDefault();
return profile;
}
catch (Exception ex)
{
ErrorLogging.Instance.Fatal(ex); // use singleton for logging
return null;
}
}
}
In this case, ProfileDetailsByID_Result is the object that I manually created using Entity Framework through the Complex Type creation process (right-click on the model diagram, select Add/Complex Type..., or use the Complex Types tree on the RHS).
A WORD OF CAUTION
Because this object's properties are derived from the sproc, EF has no way of knowing if a property is nullable. For any nullable property types, you must manually configure these by selecting the property and setting its it's Nullable property to true.