I wrote the following method.
public T GetByID(int id)
{
var dbcontext = DB;
var table = dbcontext.GetTable<T>();
return table.ToList().SingleOrDefault(e => Convert.ToInt16(e.GetType().GetProperties().First().GetValue(e, null)) == id);
}
Basically it's a method in a Generic class where T is a class in a DataContext.
The method gets the table from the type of T (GetTable) and checks for the first property (always being the ID) to the inputted parameter.
The problem with this is I had to convert the table of elements to a list first to execute a GetType on the property, but this is not very convenient because all the elements of the table have to be enumerated and converted to a List.
How can I refactor this method to avoid a ToList on the whole table?
[Update]
The reason I can't execute the Where directly on the table is because I receive this exception:
Method 'System.Reflection.PropertyInfo[] GetProperties()' has no supported translation to SQL.
Because GetProperties can't be translated to SQL.
[Update]
Some people have suggested using an interface for T, but the problem is that the T parameter will be a class that is auto generated in [DataContextName].designer.cs, and thus I cannot make it implement an interface (and it's not feasible implementing the interfaces for all these "database classes" of LINQ; and also, the file will be regenerated once I add new tables to the DataContext, thus loosing all the written data).
So, there has to be a better way to do this...
[Update]
I have now implemented my code like Neil Williams' suggestion, but I'm still having problems. Here are excerpts of the code:
Interface:
public interface IHasID
{
int ID { get; set; }
}
DataContext [View Code]:
namespace MusicRepo_DataContext
{
partial class Artist : IHasID
{
public int ID
{
get { return ArtistID; }
set { throw new System.NotImplementedException(); }
}
}
}
Generic Method:
public class DBAccess<T> where T : class, IHasID,new()
{
public T GetByID(int id)
{
var dbcontext = DB;
var table = dbcontext.GetTable<T>();
return table.SingleOrDefault(e => e.ID.Equals(id));
}
}
The exception is being thrown on this line: return table.SingleOrDefault(e => e.ID.Equals(id)); and the exception is:
System.NotSupportedException: The
member
'MusicRepo_DataContext.IHasID.ID' has
no supported translation to SQL.
[Update] Solution:
With the help of Denis Troller's posted answer and the link to the post at the Code Rant blog, I finally managed to find a solution:
public static PropertyInfo GetPrimaryKey(this Type entityType)
{
foreach (PropertyInfo property in entityType.GetProperties())
{
ColumnAttribute[] attributes = (ColumnAttribute[])property.GetCustomAttributes(typeof(ColumnAttribute), true);
if (attributes.Length == 1)
{
ColumnAttribute columnAttribute = attributes[0];
if (columnAttribute.IsPrimaryKey)
{
if (property.PropertyType != typeof(int))
{
throw new ApplicationException(string.Format("Primary key, '{0}', of type '{1}' is not int",
property.Name, entityType));
}
return property;
}
}
}
throw new ApplicationException(string.Format("No primary key defined for type {0}", entityType.Name));
}
public T GetByID(int id)
{
var dbcontext = DB;
var itemParameter = Expression.Parameter(typeof (T), "item");
var whereExpression = Expression.Lambda<Func<T, bool>>
(
Expression.Equal(
Expression.Property(
itemParameter,
typeof (T).GetPrimaryKey().Name
),
Expression.Constant(id)
),
new[] {itemParameter}
);
return dbcontext.GetTable<T>().Where(whereExpression).Single();
}
What you need is to build an expression tree that LINQ to SQL can understand. Assuming your "id" property is always named "id":
public virtual T GetById<T>(short id)
{
var itemParameter = Expression.Parameter(typeof(T), "item");
var whereExpression = Expression.Lambda<Func<T, bool>>
(
Expression.Equal(
Expression.Property(
itemParameter,
"id"
),
Expression.Constant(id)
),
new[] { itemParameter }
);
var table = DB.GetTable<T>();
return table.Where(whereExpression).Single();
}
This should do the trick. It was shamelessly borrowed from this blog.
This is basically what LINQ to SQL does when you write a query like
var Q = from t in Context.GetTable<T)()
where t.id == id
select t;
You just do the work for LTS because the compiler cannot create that for you, since nothing can enforce that T has an "id" property, and you cannot map an arbitrary "id" property from an interface to the database.
==== UPDATE ====
OK, here's a simple implementation for finding the primary key name, assuming there is only one (not a composite primary key), and assuming all is well type-wise (that is, your primary key is compatible with the "short" type you use in the GetById function):
public virtual T GetById<T>(short id)
{
var itemParameter = Expression.Parameter(typeof(T), "item");
var whereExpression = Expression.Lambda<Func<T, bool>>
(
Expression.Equal(
Expression.Property(
itemParameter,
GetPrimaryKeyName<T>()
),
Expression.Constant(id)
),
new[] { itemParameter }
);
var table = DB.GetTable<T>();
return table.Where(whereExpression).Single();
}
public string GetPrimaryKeyName<T>()
{
var type = Mapping.GetMetaType(typeof(T));
var PK = (from m in type.DataMembers
where m.IsPrimaryKey
select m).Single();
return PK.Name;
}
What if you rework this to use GetTable().Where(...), and put your filtering there?
That would be more efficient, since the Where extension method should take care of your filtering better than fetching the entire table into a list.
Some thoughts...
Just remove the ToList() call, SingleOrDefault works with an IEnumerably which I presume table is.
Cache the call to e.GetType().GetProperties().First() to get the PropertyInfo returned.
Cant you just add a constraint to T that would force them to implement an interface that exposes the Id property?
Maybe executing a query might be a good idea.
public static T GetByID(int id)
{
Type type = typeof(T);
//get table name
var att = type.GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault();
string tablename = att == null ? "" : ((TableAttribute)att).Name;
//make a query
if (string.IsNullOrEmpty(tablename))
return null;
else
{
string query = string.Format("Select * from {0} where {1} = {2}", new object[] { tablename, "ID", id });
//and execute
return dbcontext.ExecuteQuery<T>(query).FirstOrDefault();
}
}
Regarding:
System.NotSupportedException: The member 'MusicRepo_DataContext.IHasID.ID' has no supported translation to SQL.
The simple workaround to your initial problem is to specify an Expression. See below, it works like a charm for me.
public interface IHasID
{
int ID { get; set; }
}
DataContext [View Code]:
namespace MusicRepo_DataContext
{
partial class Artist : IHasID
{
[Column(Name = "ArtistID", Expression = "ArtistID")]
public int ID
{
get { return ArtistID; }
set { throw new System.NotImplementedException(); }
}
}
}
Ok, check this demo implementation. Is attempt to get generic GetById with datacontext(Linq To Sql). Also compatible with multi key property.
using System;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;
public static class Programm
{
public const string ConnectionString = #"Data Source=localhost\SQLEXPRESS;Initial Catalog=TestDb2;Persist Security Info=True;integrated Security=True";
static void Main()
{
using (var dc = new DataContextDom(ConnectionString))
{
if (dc.DatabaseExists())
dc.DeleteDatabase();
dc.CreateDatabase();
dc.GetTable<DataHelperDb1>().InsertOnSubmit(new DataHelperDb1() { Name = "DataHelperDb1Desc1", Id = 1 });
dc.GetTable<DataHelperDb2>().InsertOnSubmit(new DataHelperDb2() { Name = "DataHelperDb2Desc1", Key1 = "A", Key2 = "1" });
dc.SubmitChanges();
Console.WriteLine("Name:" + GetByID(dc.GetTable<DataHelperDb1>(), 1).Name);
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("Name:" + GetByID(dc.GetTable<DataHelperDb2>(), new PkClass { Key1 = "A", Key2 = "1" }).Name);
}
}
//Datacontext definition
[Database(Name = "TestDb2")]
public class DataContextDom : DataContext
{
public DataContextDom(string connStr) : base(connStr) { }
public Table<DataHelperDb1> DataHelperDb1;
public Table<DataHelperDb2> DataHelperD2;
}
[Table(Name = "DataHelperDb1")]
public class DataHelperDb1 : Entity<DataHelperDb1, int>
{
[Column(IsPrimaryKey = true)]
public int Id { get; set; }
[Column]
public string Name { get; set; }
}
public class PkClass
{
public string Key1 { get; set; }
public string Key2 { get; set; }
}
[Table(Name = "DataHelperDb2")]
public class DataHelperDb2 : Entity<DataHelperDb2, PkClass>
{
[Column(IsPrimaryKey = true)]
public string Key1 { get; set; }
[Column(IsPrimaryKey = true)]
public string Key2 { get; set; }
[Column]
public string Name { get; set; }
}
public class Entity<TEntity, TKey> where TEntity : new()
{
public static TEntity SearchObjInstance(TKey key)
{
var res = new TEntity();
var targhetPropertyInfos = GetPrimaryKey<TEntity>().ToList();
if (targhetPropertyInfos.Count == 1)
{
targhetPropertyInfos.First().SetValue(res, key, null);
}
else if (targhetPropertyInfos.Count > 1)
{
var sourcePropertyInfos = key.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var sourcePi in sourcePropertyInfos)
{
var destinationPi = targhetPropertyInfos.FirstOrDefault(x => x.Name == sourcePi.Name);
if (destinationPi == null || sourcePi.PropertyType != destinationPi.PropertyType)
continue;
object value = sourcePi.GetValue(key, null);
destinationPi.SetValue(res, value, null);
}
}
return res;
}
}
public static IEnumerable<PropertyInfo> GetPrimaryKey<T>()
{
foreach (var info in typeof(T).GetProperties().ToList())
{
if (info.GetCustomAttributes(false)
.Where(x => x.GetType() == typeof(ColumnAttribute))
.Where(x => ((ColumnAttribute)x).IsPrimaryKey)
.Any())
yield return info;
}
}
//Move in repository pattern
public static TEntity GetByID<TEntity, TKey>(Table<TEntity> source, TKey id) where TEntity : Entity<TEntity, TKey>, new()
{
var searchObj = Entity<TEntity, TKey>.SearchObjInstance(id);
Console.WriteLine(source.Where(e => e.Equals(searchObj)).ToString());
return source.Single(e => e.Equals(searchObj));
}
}
Result:
SELECT [t0].[Id], [t0].[Name]
FROM [DataHelperDb1] AS [t0]
WHERE [t0].[Id] = #p0
Name:DataHelperDb1Desc1
SELECT [t0].[Key1], [t0].[Key2], [t0].[Name]
FROM [DataHelperDb2] AS [t0]
WHERE ([t0].[Key1] = #p0) AND ([t0].[Key2] = #p1)
Name:DataHelperDb2Desc1
Related
On an API I need dynamic include, but EF Core does not support string-based include.
Because of this, I created a mapper which maps strings to lambda expressions added to a list as:
List<List<Expression>> expressions = new List<List<Expression>>();
Consider the following specific types:
public class EFContext
{
public DbSet<P1> P1s { get; set; }
public DbSet<P1> P2s { get; set; }
public DbSet<P1> P3s { get; set; }
}
public class P1
{
public P2 P2 { get; set; }
public P3 P3 { get; set; }
}
public class P2
{
public P3 P3 { get; set; }
}
public class P3 { }
Include and ThenInclude are normally used as follows:
EFContext efcontext = new EFContext();
IQueryable<P1> result = efcontext.P1s
.Include(p1 => p1.P2)
.ThenInclude(p2 => p2.P3)
.Include(p1 => p1.P3);
They can also be used the following way:
Expression<Func<P1, P2>> p1p2 = p1 => p1.P2;
Expression<Func<P1, P3>> p1p3 = p1 => p1.P3;
Expression<Func<P2, P3>> p2p3 = p2 => p2.P3;
List<List<Expression>> expressions = new List<List<Expression>>
{
new List<Expression> { p1p2, p1p3 },
new List<Expression> { p2p3 }
};
EFContext efcontext = new EFContext();
IIncludableQueryable<P1, P2> q1 = EntityFrameworkQueryableExtensions
.Include(efcontext.P1s, p1p2);
IIncludableQueryable<P1, P3> q2 = EntityFrameworkQueryableExtensions
.ThenInclude(q1, p2p3);
IIncludableQueryable<P1, P3> q3 = EntityFrameworkQueryableExtensions
.Include(q2, p1p3);
result = q3.AsQueryable();
The problem is that my method receives a list of Expressions and I only have the base type in T:
public static class IncludeExtensions<T>
{
public static IQueryable<T> IncludeAll(this IQueryable<T> collection, List<List<Expression>> expressions)
{
MethodInfo include = typeof(EntityFrameworkQueryableExtensions)
.GetTypeInfo()
.GetDeclaredMethods(nameof(EntityFrameworkQueryableExtensions.Include))
.Single(mi => mi.GetParameters()
.Any(pi => pi.Name == "navigationPropertyPath"));
MethodInfo includeAfterCollection = typeof(EntityFrameworkQueryableExtensions)
.GetTypeInfo()
.GetDeclaredMethods(nameof(EntityFrameworkQueryableExtensions.ThenInclude))
.Single(mi =>
!mi.GetParameters()[0].ParameterType.GenericTypeArguments[1].IsGenericParameter);
MethodInfo includeAfterReference = typeof(EntityFrameworkQueryableExtensions)
.GetTypeInfo()
.GetDeclaredMethods(nameof(EntityFrameworkQueryableExtensions.ThenInclude))
.Single(mi => mi.GetParameters()[0].ParameterType.GenericTypeArguments[1].IsGenericParameter);
foreach (List<Expression> path in expressions)
{
bool start = true;
foreach (Expression expression in path)
{
if (start)
{
MethodInfo method = include.MakeGenericMethod(typeof(T), ((LambdaExpression)expression).ReturnType);
IIncludableQueryable<T,?> result = method.Invoke(null, new Object[] { collection, expression });
start = false;
}
else
{
MethodInfo method = includeAfterReference.MakeGenericMethod(typeof(T), typeof(?), ((LambdaExpression)expression).ReturnType);
IIncludableQueryable <T,?> result = method.Invoke(null, new Object[] { collection, expression });
}
}
}
return collection; // (to be replaced by final as Queryable)
}
}
The main problem has been resolving the correct types for each Include and ThenInclude step and also which ThenInclude to use.
Is this even possible with the current EF7 Core? Did someone find a solution for dynamic Include?
The Include and ThenIncludeAfterReference and ThenIncludeAfterCollection methods are part of EntityFrameworkQueryableExtensions class in EntityFramework Github's repository.
Update:
Starting with v1.1.0, the string based include is now part of EF Core, so the issue and the below solution are obsolete.
Original answer:
Interesting exercise for the weekend.
Solution:
I've ended up with the following extension method:
public static class IncludeExtensions
{
private static readonly MethodInfo IncludeMethodInfo = typeof(EntityFrameworkQueryableExtensions).GetTypeInfo()
.GetDeclaredMethods(nameof(EntityFrameworkQueryableExtensions.Include)).Single(mi => mi.GetParameters().Any(pi => pi.Name == "navigationPropertyPath"));
private static readonly MethodInfo IncludeAfterCollectionMethodInfo = typeof(EntityFrameworkQueryableExtensions).GetTypeInfo()
.GetDeclaredMethods(nameof(EntityFrameworkQueryableExtensions.ThenInclude)).Single(mi => !mi.GetParameters()[0].ParameterType.GenericTypeArguments[1].IsGenericParameter);
private static readonly MethodInfo IncludeAfterReferenceMethodInfo = typeof(EntityFrameworkQueryableExtensions).GetTypeInfo()
.GetDeclaredMethods(nameof(EntityFrameworkQueryableExtensions.ThenInclude)).Single(mi => mi.GetParameters()[0].ParameterType.GenericTypeArguments[1].IsGenericParameter);
public static IQueryable<TEntity> Include<TEntity>(this IQueryable<TEntity> source, params string[] propertyPaths)
where TEntity : class
{
var entityType = typeof(TEntity);
object query = source;
foreach (var propertyPath in propertyPaths)
{
Type prevPropertyType = null;
foreach (var propertyName in propertyPath.Split('.'))
{
Type parameterType;
MethodInfo method;
if (prevPropertyType == null)
{
parameterType = entityType;
method = IncludeMethodInfo;
}
else
{
parameterType = prevPropertyType;
method = IncludeAfterReferenceMethodInfo;
if (parameterType.IsConstructedGenericType && parameterType.GenericTypeArguments.Length == 1)
{
var elementType = parameterType.GenericTypeArguments[0];
var collectionType = typeof(ICollection<>).MakeGenericType(elementType);
if (collectionType.IsAssignableFrom(parameterType))
{
parameterType = elementType;
method = IncludeAfterCollectionMethodInfo;
}
}
}
var parameter = Expression.Parameter(parameterType, "e");
var property = Expression.PropertyOrField(parameter, propertyName);
if (prevPropertyType == null)
method = method.MakeGenericMethod(entityType, property.Type);
else
method = method.MakeGenericMethod(entityType, parameter.Type, property.Type);
query = method.Invoke(null, new object[] { query, Expression.Lambda(property, parameter) });
prevPropertyType = property.Type;
}
}
return (IQueryable<TEntity>)query;
}
}
Test:
Model:
public class P
{
public int Id { get; set; }
public string Info { get; set; }
}
public class P1 : P
{
public P2 P2 { get; set; }
public P3 P3 { get; set; }
}
public class P2 : P
{
public P4 P4 { get; set; }
public ICollection<P1> P1s { get; set; }
}
public class P3 : P
{
public ICollection<P1> P1s { get; set; }
}
public class P4 : P
{
public ICollection<P2> P2s { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<P1> P1s { get; set; }
public DbSet<P2> P2s { get; set; }
public DbSet<P3> P3s { get; set; }
public DbSet<P4> P4s { get; set; }
// ...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<P1>().HasOne(e => e.P2).WithMany(e => e.P1s).HasForeignKey("P2Id").IsRequired();
modelBuilder.Entity<P1>().HasOne(e => e.P3).WithMany(e => e.P1s).HasForeignKey("P3Id").IsRequired();
modelBuilder.Entity<P2>().HasOne(e => e.P4).WithMany(e => e.P2s).HasForeignKey("P4Id").IsRequired();
base.OnModelCreating(modelBuilder);
}
}
Usage:
var db = new MyDbContext();
// Sample query using Include/ThenInclude
var queryA = db.P3s
.Include(e => e.P1s)
.ThenInclude(e => e.P2)
.ThenInclude(e => e.P4)
.Include(e => e.P1s)
.ThenInclude(e => e.P3);
// The same query using string Includes
var queryB = db.P3s
.Include("P1s.P2.P4", "P1s.P3");
How it works:
Given a type TEntity and a string property path of the form Prop1.Prop2...PropN, we split the path and do the following:
For the first property we just call via reflection the EntityFrameworkQueryableExtensions.Include method:
public static IIncludableQueryable<TEntity, TProperty>
Include<TEntity, TProperty>
(
this IQueryable<TEntity> source,
Expression<Func<TEntity, TProperty>> navigationPropertyPath
)
and store the result. We know TEntity and TProperty is the type of the property.
For the next properties it's a bit more complex. We need to call one of the following ThenInclude overloads:
public static IIncludableQueryable<TEntity, TProperty>
ThenInclude<TEntity, TPreviousProperty, TProperty>
(
this IIncludableQueryable<TEntity, ICollection<TPreviousProperty>> source,
Expression<Func<TPreviousProperty, TProperty>> navigationPropertyPath
)
and
public static IIncludableQueryable<TEntity, TProperty>
ThenInclude<TEntity, TPreviousProperty, TProperty>
(
this IIncludableQueryable<TEntity, TPreviousProperty> source,
Expression<Func<TPreviousProperty, TProperty>> navigationPropertyPath
)
source is the current result. TEntity is one and the same for all calls. But what is TPreviousProperty and how we decide which method to call.
Well, first we use a variable to remember what was the TProperty in the previous call. Then we check if it is a collection property type, and if yes, we call the first overload with TPreviousProperty type extracted from the generic arguments of the collection type, otherwise simply call the second overload with that type.
And that's all. Nothing fancy, just emulating an explicit Include / ThenInclude call chains via reflection.
String-based Include() shipped in EF Core 1.1. I would suggest you try upgrading and removing any workarounds you had to add to your code to address this limitation.
Creating an "IncludeAll" extension on query will require a different approach from what you have initially done.
EF Core does expression interpretation. When it sees the .Include method, it interprets this expression into creating additional queries. (See RelationalQueryModelVisitor.cs and IncludeExpressionVisitor.cs).
One approach would be to add an additional expression visitor that handles your IncludeAll extension. Another (and probably better) approach would be to interpret the expression tree from .IncludeAll to the appropriate .Includes and then let EF handle the includes normally. An implementation of either is non-trivial and beyond the scope of a SO answer.
String-based Include() shipped in EF Core 1.1. If you keep this extension you will get error "Ambiguous match found". I spent half day to search solution for this error. Finally i removed above extension and error was resolved.
I am using EF5 and I have some entities that I wrote myself and also wrote a function that adds all the mappings to the modelbuilder configurations.
Running a simple test query, I can query items from a table successfully but when I try to add a new item and save, I get an exception that the primary key of my entity is null, even though I gave it a value.
It's quite possible that I messed up the mappings, but I don't know why it would work for a query and not a save.
public class User : IMappedEntity
{
[Key]
[Column("USER_ID")]
public int UserID { get; set; }
[Column("FIRST_NAME")]
public String FirstName { get; set; }
[Column("LAST_NAME")]
public String LastName { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingEntitySetNameConvention>();
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
var addMethod = (from m in (modelBuilder.Configurations).GetType().GetMethods()
where m.Name == "Add"
&& m.GetParameters().Count() == 1
&& m.GetParameters()[0].ParameterType.Name == typeof(EntityTypeConfiguration<>).Name
select m).First();
if(mappings != null)
{
foreach(var map in mappings)
{
if(map != null && !mappedTypes.Contains(map.GetType()))
{
var thisType = map.GetType();
if (thisType.IsGenericType)
{
thisType = map.GetType().GenericTypeArguments[0];
}
var thisAddMethod = addMethod.MakeGenericMethod(new[] {thisType});
thisAddMethod.Invoke(modelBuilder.Configurations, new[] { map });
mappedTypes.Add(map.GetType());
}
}
}
}
private List<Object> BuildMappings(IEnumerable<Type> types)
{
List<Object> results = new List<Object>();
var pkType = typeof(KeyAttribute);
var dbGenType = typeof(DatabaseGeneratedAttribute);
foreach (Type t in types)
{
String tableName = GetTableName(t);
String schemaName = GetSchema(t);
var mappingType = typeof(EntityTypeConfiguration<>).MakeGenericType(t);
dynamic mapping = Activator.CreateInstance(mappingType);
if (!String.IsNullOrWhiteSpace(schemaName))
mapping.ToTable(tableName, SchemaName.ToUpper());
else
mapping.ToTable(tableName);
var keys = new List<PropertyInfo>();
foreach (PropertyInfo prop in t.GetProperties())
{
String columnName = prop.Name;
if(Attribute.IsDefined(prop, typeof(ColumnAttribute)))
{
columnName = (prop.GetCustomAttribute(typeof(ColumnAttribute)) as ColumnAttribute).Name;
}
if(Attribute.IsDefined(prop, pkType))
keys.Add(prop);
var genFunc = (typeof(Func<,>)).MakeGenericType(t, prop.PropertyType);
var param = Expression.Parameter(t, "t");
var body = Expression.PropertyOrField(param, prop.Name);
dynamic lambda = Expression.Lambda(genFunc, body, new ParameterExpression[] { param });
//if (prop.PropertyType == typeof(Guid) || prop.PropertyType == typeof(Nullable<Guid>))
//{
// mapping.Property(lambda).HasColumnType("Guid");
//}
//else
mapping.Property(lambda).HasColumnName(columnName);
if (Attribute.IsDefined(prop, dbGenType))
mapping.Property(lambda).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
}
if (keys.Count == 0)
throw new InvalidOperationException("Entity must have a primary key");
dynamic entKey = null;
if(keys.Count == 1)
{
var genFunc = (typeof(Func<,>)).MakeGenericType(t, keys[0].PropertyType);
var param = Expression.Parameter(t, "t");
var body = Expression.PropertyOrField(param, keys[0].Name);
entKey = Expression.Lambda(genFunc, body, new ParameterExpression[] { param });
}
else
{
//if entity uses a compound key, it must have a function named "GetPrimaryKey()" which returns Expression<Func<EntityType,Object>>
//this is because I can't create an expression tree that creates an anonymous type
entKey = t.GetMethod("GetPrimaryKey");
}
mapping.HasKey(entKey);
results.Add(mapping);
}
return results;
}
static void Main(string[] args)
{
using (var ctx = new DQSA.Data.DBContext("DQSATEST"))
{
var xxx = (from u in ctx.Query<DQSA.Data.Entities.User>()
select u).ToList(); //this works, I can see my user
ctx.Set<DQSA.Data.Entities.User>().Add(new DQSA.Data.Entities.User()
{ UserID = 0,
FirstName="Sam",
LastName="Sam"
});
ctx.SaveChanges(); //get an exception here
xxx = (from u in ctx.Query<DQSA.Data.Entities.User>()
select u).ToList();
}
}
It looks like your UserID property is being mapped as an Identity column by convention so the EF query provider thinks it doesn't need to insert that value and the database complains because the field is not nullable.
You can override the convention in your model by using the DatabaseGeneratedAttribute ...
public class User : IMappedEntity
{
[Key]
[Column("USER_ID")]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int UserID { get; set; }
...
}
or by removing the convention globally (in your DbContext's OnModelCreating() method) ...
modelBuilder.Conventions.Remove<StoreGeneratedIdentityKeyConvention>();
I think you need to try to seed with one or few records then context.SaveChanges()
by default, entity framework should mark the primary key column of a new table created with Code First as an identity column. Did the database exist prior to your code, or did you use code first to create it?
Can you verify in Management Studio that the column has identity turned on for that field?
Is there a way to convertFunc<IQueryable<TD>, IOrderedQueryable<TD>> to Func<IQueryable<TE>, IOrderedQueryable<TE>>.
Let's say I have classes Country and CountryModel.
class CountryModel
{
public string Name {get;set;}
}
class Country{
public string Name{get;set;}
}
class Repo{
public IEnumerable<TD> Get(
Func<IQueryable<TD>, IOrderedQueryable<TD>> orderBy = null)
{
IQueryable<TEntityModel> query = CurrentDbSet;
return orderBy(query).ToList(); // Convert orderBy to TE.
}
}
Using the above method I would pass CountryModel instance. But the query has to happen the entity type Country.
There might be some syntax errors. Apologies for that.
public class Repo
{
public IEnumerable<TD> Get<TD, TE>(Func<IQueryable<TD>, IOrderedQueryable<TD>> orderBy = null)
{
IQueryable<TD> query = new List<TE>().Select(t => Convert<TD, TE>(t)).AsQueryable();
return orderBy(query).AsEnumerable(); // Convert orderBy to TE.
}
public TD Convert<TD, TE>(TE input) where TD : class
{
return input as TD;
}
}
If your type TE can be casted to the type TD this should work.
You can define explicit or implicit operator in your CountryModel to convert from Country
You may find AutoMapper to be very useful.
public static class MappingExtensions
{
static MappingExtensions()
{
Mapper.CreateMap<CustomAlerts, Domain.Models.CustomAlerts>();
Mapper.CreateMap<Domain.Models.CustomAlerts, CustomAlerts>();
//add mappings for each set of objects here.
//Remember to map both ways(from x to y and from y to x)
}
//map single objects
public static TDestination Map<TSource, TDestination>(TSource item)
{
return Mapper.Map<TSource, TDestination>(item);
}
//map collections
public static IEnumerable<TDestination> Map<TSource, TDestination>(IEnumerable<TSource> item)
{
return Mapper.Map<IEnumerable<TSource>, IEnumerable<TDestination>>(item);
}
}
Then in my code, I can do the following:
var TodayDate = DateTime.Now.AddDays(1);
var Alerts = DB.CustomAlerts
.Where(x => x.EndDate >= TodayDate)
.OrderByDescending(x => x.DateCreated)
.Skip(((id - 1) * 50))
.Take(50);
return Mapping.MappingExtensions.Map<CustomAlert,Models.CustomAlert>(Alerts).ToList();
Using AutoMapper and wrapping your Func with Expression should help you:
// Initialize AutoMapper
Mapper.Initialize(cfg =>
{
cfg.CreateMap<TE, TD>();
cfg.CreateMap<TD, TE>();
});
public class Repo
{
// Wrap Func with Expression
public IEnumerable<TD> Get(Expression<Func<IQueryable<TD>, IOrderedQueryable<TD>>> orderBy = null)
{
var orderByExpr = Mapper.Map<Expression<Func<IQueryable<TE>, IOrderedQueryable<TE>>>>(orderBy);
IQueryable<TE> query = CurrentDbSet;
// Compile expression and execute as function
var items = orderByExpr.Compile()(query).ToList();
// Map back to list of TD
return Mapper.Map<IEnumerable<TD>>(items);
}
}
note: it's a long post, please scroll to the bottom to see questions - hopefully that will make it easier to understand my problem. Thanks!
I have "Member" model which is defined as follows:
public class Member
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string ScreenName { get; set; }
[NotMapped]
public string RealName
{
get { return (FirstName + " " + LastName).TrimEnd(); }
}
[NotMapped]
public string DisplayName
{
get
{
return string.IsNullOrEmpty(ScreenName) ? RealName : ScreenName;
}
}
}
This is existing project, and model, and I don't want to change this. Now we got a request to enable profile retrieval by DisplayName:
public Member GetMemberByDisplayName(string displayName)
{
var member = this.memberRepository
.FirstOrDefault(m => m.DisplayName == displayName);
return member;
}
This code does not work because DisplayName is not mapped to a field in database. Okay, I will make an expression then:
public Member GetMemberByDisplayName(string displayName)
{
Expression<Func<Member, bool>> displayNameSearchExpr = m => (
string.IsNullOrEmpty(m.ScreenName)
? (m.Name + " " + m.LastName).TrimEnd()
: m.ScreenName
) == displayName;
var member = this.memberRepository
.FirstOrDefault(displayNameSearchExpr);
return member;
}
this works. The only problem is that business logic to generate display name is copy/pasted in 2 different places. I want to avoid this. But I do not understand how to do this. The best I came with is the following:
public class Member
{
public static Expression<Func<Member, string>> GetDisplayNameExpression()
{
return m => (
string.IsNullOrEmpty(m.ScreenName)
? (m.Name + " " + m.LastName).TrimEnd()
: m.ScreenName
);
}
public static Expression<Func<Member, bool>> FilterMemberByDisplayNameExpression(string displayName)
{
return m => (
string.IsNullOrEmpty(m.ScreenName)
? (m.Name + " " + m.LastName).TrimEnd()
: m.ScreenName
) == displayName;
}
private static readonly Func<Member, string> GetDisplayNameExpressionCompiled = GetDisplayNameExpression().Compile();
[NotMapped]
public string DisplayName
{
get
{
return GetDisplayNameExpressionCompiled(this);
}
}
[NotMapped]
public string RealName
{
get { return (FirstName + " " + LastName).TrimEnd(); }
}
}
Questions:
(1) How to reuse GetDisplayNameExpression() inside FilterMemberByDisplayNameExpression()? I tried Expression.Invoke:
public static Expression<Func<Member, bool>> FilterMemberByDisplayNameExpression(string displayName)
{
Expression<Func<string, bool>> e0 = s => s == displayName;
var e1 = GetDisplayNameExpression();
var combinedExpression = Expression.Lambda<Func<Member, bool>>(
Expression.Invoke(e0, e1.Body), e1.Parameters);
return combinedExpression;
}
but I get the following error from the provider:
The LINQ expression node type 'Invoke' is not supported in LINQ to
Entities.
(2) Is it a good approach to use Expression.Compile() inside DisplayName property? Any issues with it?
(3) How to move RealName logic inside GetDisplayNameExpression()? I think I have to create another expression and another compiled expression, but I do not understand how to CALL RealNameExpression from inside GetDisplayNameExpression().
Thank you.
I can fix your expression generator, and I can compose your GetDisplayNameExpression (so 1 and 3)
public class Member
{
public string ScreenName { get; set; }
public string Name { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public static Expression<Func<Member, string>> GetRealNameExpression()
{
return m => (m.Name + " " + m.LastName).TrimEnd();
}
public static Expression<Func<Member, string>> GetDisplayNameExpression()
{
var isNullOrEmpty = typeof(string).GetMethod("IsNullOrEmpty", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null);
var e0 = GetRealNameExpression();
var par1 = e0.Parameters[0];
// Done in this way, refactoring will correctly rename m.ScreenName
// We could have used a similar trick for string.IsNullOrEmpty,
// but it would have been useless, because its name and signature won't
// ever change.
Expression<Func<Member, string>> e1 = m => m.ScreenName;
var screenName = (MemberExpression)e1.Body;
var prop = Expression.Property(par1, (PropertyInfo)screenName.Member);
var condition = Expression.Condition(Expression.Call(null, isNullOrEmpty, prop), e0.Body, prop);
var combinedExpression = Expression.Lambda<Func<Member, string>>(condition, par1);
return combinedExpression;
}
private static readonly Func<Member, string> GetDisplayNameExpressionCompiled = GetDisplayNameExpression().Compile();
private static readonly Func<Member, string> GetRealNameExpressionCompiled = GetRealNameExpression().Compile();
public string DisplayName
{
get
{
return GetDisplayNameExpressionCompiled(this);
}
}
public string RealName
{
get
{
return GetRealNameExpressionCompiled(this);
}
}
public static Expression<Func<Member, bool>> FilterMemberByDisplayNameExpression(string displayName)
{
var e0 = GetDisplayNameExpression();
var par1 = e0.Parameters[0];
var combinedExpression = Expression.Lambda<Func<Member, bool>>(
Expression.Equal(e0.Body, Expression.Constant(displayName)), par1);
return combinedExpression;
}
Note how I reuse the same parameter of the GetDisplayNameExpression expression e1.Parameters[0] (put in par1) so that I don't have to rewrite the expression (otherwise I would have needed to use an expression rewriter).
We could use this trick because we had only a single expression to handle, to which we had to attach some new code. Totally different (we would have needed an expression rewriter) would be the case of trying to combine two expressions (for example to do a GetRealNameExpression() + " " + GetDisplayNameExpression(), both require as a parameter a Member, but their parameters are separate... Probably this https://stackoverflow.com/a/5431309/613130 would work...
For the 2, I don't see any problem. You are correctly using static readonly. But please, look at GetDisplayNameExpression and think "is it better some business code duplication pay or that?"
Generic solution
Now... I was quite sure it was doable... and in fact it is doable: an expression "expander" that "expands" "special properties" to their Expression(s) "automagically".
public static class QueryableEx
{
private static readonly ConcurrentDictionary<Type, Dictionary<PropertyInfo, LambdaExpression>> expressions = new ConcurrentDictionary<Type, Dictionary<PropertyInfo, LambdaExpression>>();
public static IQueryable<T> Expand<T>(this IQueryable<T> query)
{
var visitor = new QueryableVisitor();
Expression expression2 = visitor.Visit(query.Expression);
return query.Expression != expression2 ? query.Provider.CreateQuery<T>(expression2) : query;
}
private static Dictionary<PropertyInfo, LambdaExpression> Get(Type type)
{
Dictionary<PropertyInfo, LambdaExpression> dict;
if (expressions.TryGetValue(type, out dict))
{
return dict;
}
var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
dict = new Dictionary<PropertyInfo, LambdaExpression>();
foreach (var prop in props)
{
var exp = type.GetMember(prop.Name + "Expression", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Where(p => p.MemberType == MemberTypes.Field || p.MemberType == MemberTypes.Property).SingleOrDefault();
if (exp == null)
{
continue;
}
if (!typeof(LambdaExpression).IsAssignableFrom(exp.MemberType == MemberTypes.Field ? ((FieldInfo)exp).FieldType : ((PropertyInfo)exp).PropertyType))
{
continue;
}
var lambda = (LambdaExpression)(exp.MemberType == MemberTypes.Field ? ((FieldInfo)exp).GetValue(null) : ((PropertyInfo)exp).GetValue(null, null));
if (prop.PropertyType != lambda.ReturnType)
{
throw new Exception(string.Format("Mismatched return type of Expression of {0}.{1}, {0}.{2}", type.Name, prop.Name, exp.Name));
}
dict[prop] = lambda;
}
// We try to save some memory, removing empty dictionaries
if (dict.Count == 0)
{
dict = null;
}
// There is no problem if multiple threads generate their "versions"
// of the dict at the same time. They are all equivalent, so the worst
// case is that some CPU cycles are wasted.
dict = expressions.GetOrAdd(type, dict);
return dict;
}
private class SingleParameterReplacer : ExpressionVisitor
{
public readonly ParameterExpression From;
public readonly Expression To;
public SingleParameterReplacer(ParameterExpression from, Expression to)
{
this.From = from;
this.To = to;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return node != this.From ? base.VisitParameter(node) : this.Visit(this.To);
}
}
private class QueryableVisitor : ExpressionVisitor
{
protected static readonly Assembly MsCorLib = typeof(int).Assembly;
protected static readonly Assembly Core = typeof(IQueryable).Assembly;
// Used to check for recursion
protected readonly List<MemberInfo> MembersBeingVisited = new List<MemberInfo>();
protected override Expression VisitMember(MemberExpression node)
{
var declaringType = node.Member.DeclaringType;
var assembly = declaringType.Assembly;
if (assembly != MsCorLib && assembly != Core && node.Member.MemberType == MemberTypes.Property)
{
var dict = QueryableEx.Get(declaringType);
LambdaExpression lambda;
if (dict != null && dict.TryGetValue((PropertyInfo)node.Member, out lambda))
{
// Anti recursion check
if (this.MembersBeingVisited.Contains(node.Member))
{
throw new Exception(string.Format("Recursively visited member. Chain: {0}", string.Join("->", this.MembersBeingVisited.Concat(new[] { node.Member }).Select(p => p.DeclaringType.Name + "." + p.Name))));
}
this.MembersBeingVisited.Add(node.Member);
// Replace the parameters of the expression with "our" reference
var body = new SingleParameterReplacer(lambda.Parameters[0], node.Expression).Visit(lambda.Body);
Expression exp = this.Visit(body);
this.MembersBeingVisited.RemoveAt(this.MembersBeingVisited.Count - 1);
return exp;
}
}
return base.VisitMember(node);
}
}
}
How does it work? Magic, reflection, fairy dust...
Does it support properties referencing other properties? Yes
What does it need?
It needs that every "special" property of name Foo has a corresponding static field/static property named FooExpression that returns an Expression<Func<Class, something>>
It needs that the query is "transformed" through the extension method Expand() at some point before the materialization/enumeration. So:
public class Member
{
// can be private/protected/internal
public static readonly Expression<Func<Member, string>> RealNameExpression =
m => (m.Name + " " + m.LastName).TrimEnd();
// Here we are referencing another "special" property, and it just works!
public static readonly Expression<Func<Member, string>> DisplayNameExpression =
m => string.IsNullOrEmpty(m.ScreenName) ? m.RealName : m.ScreenName;
public string RealName
{
get
{
// return the real name however you want, probably reusing
// the expression through a compiled readonly
// RealNameExpressionCompiled as you had done
}
}
public string DisplayName
{
get
{
}
}
}
// Note the use of .Expand();
var res = (from p in ctx.Member
where p.RealName == "Something" || p.RealName.Contains("Anything") ||
p.DisplayName == "Foo"
select new { p.RealName, p.DisplayName, p.Name }).Expand();
// now you can use res normally.
Limits 1: one problem is with methods like Single(Expression), First(Expression), Any(Expression) and similar, that don't return an IQueryable. Change by using first a Where(Expression).Expand().Single()
Limit 2: "special" properties can't reference themselves in cycles. So if A uses B, B can't use A, and tricks like using ternary expressions won't make it work.
Recently I was faced with the need to keep some business logic in expressions which allow to use it in SQL queries and in .net code. I've moved some code which help with this to github repo. I've implemented the easy way to combine and reuse expressions. See my example:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public Company Company { get; set; }
public static Expression<Func<Person, string>> FirstNameExpression
{
get { return x => x.FirstName; }
}
public static Expression<Func<Person, string>> LastNameExpression
{
get { return x => x.LastName; }
}
public static Expression<Func<Person, string>> FullNameExpression
{
//get { return FirstNameExpression.Plus(" ").Plus(LastNameExpression); }
// or
get { return x => FirstNameExpression.Wrap(x) + " " + LastNameExpression.Wrap(x); }
}
public static Expression<Func<Person, string>> SearchFieldExpression
{
get
{
return
p => string.IsNullOrEmpty(FirstNameExpression.Wrap(p)) ? LastNameExpression.Wrap(p) : FullNameExpression.Wrap(p);
}
}
public static Expression<Func<Person, bool>> GetFilterExpression(string q)
{
return p => SearchFieldExpression.Wrap(p) == q;
}
}
Extension method .Wrap() is the marker only:
public static TDest Wrap<TSource, TDest>(this Expression<Func<TSource, TDest>> expr, TSource val)
{
throw new NotImplementedException("Used only as expression transform marker");
}
What is FullName? It's FirstName + " " + LastName where FirstName and LastName - strings. But we have expressions, it's not a real value and we need to combine these expressions. Method .Wrap(val) help us to move to a simple code. We don't need to write any composers or other visitors for expressions. All this magic is already done by method .Wrap(val) where val - parameter which will be passed to called lambda expression.
So we describe expressions using other expressions. To get the full expression need to expand all usages of Wrap method, so you need to call method Unwrap on Expression (or IQueryable).
See sample:
using (var context = new Entities())
{
var originalExpr = Person.GetFilterExpression("ivan");
Console.WriteLine("Original: " + originalExpr);
Console.WriteLine();
var expr = Person.GetFilterExpression("ivan").Unwrap();
Console.WriteLine("Unwrapped: " + expr);
Console.WriteLine();
var persons = context.Persons.Where(Person.GetFilterExpression("ivan").Unwrap());
Console.WriteLine("SQL Query 1: " + persons);
Console.WriteLine();
var companies = context.Companies.Where(x => x.Persons.Any(Person.GetFilterExpression("abc").Wrap())).Unwrap(); // here we use .Wrap method without parameters, because .Persons is the ICollection (not IQueryable) and we can't pass Expression<Func<T, bool>> as Func<T, bool>, so we need it for successful compilation. Unwrap method expand Wrap method usage and convert Expression to lambda function.
Console.WriteLine("SQL Query 2: " + companies);
Console.WriteLine();
var traceSql = persons.ToString();
}
Console output:
Original: p => (Person.SearchFieldExpression.Wrap(p) ==
value(QueryMapper.Exampl es.Person+<>c__DisplayClass0).q)
Unwrapped: p => (IIF(IsNullOrEmpty(p.FirstName), p.LastName,
((p.FirstName + " " ) + p.LastName)) ==
value(QueryMapper.Examples.Person+<>c__DisplayClass0).q)
SQL Query 1: SELECT [Extent1].[Id] AS [Id], [Extent1].[FirstName] AS
[FirstName], [Extent1].[LastName] AS [LastName], [Extent1].[Age] AS
[Age], [Extent1].[Company_Id] AS [Company_Id] FROM [dbo].[People] AS
[Extent1] WHERE (CASE WHEN (([Extent1].[FirstName] IS NULL) OR ((
CAST(LEN([Extent1].[Firs tName]) AS int)) = 0)) THEN
[Extent1].[LastName] ELSE [Extent1].[FirstName] + N' ' +
[Extent1].[LastName] END) = #p_linq_0
SQL Query 2: SELECT [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name]
FROM [dbo].[Companies] AS [Extent1] WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[People] AS [Extent2]
WHERE ([Extent1].[Id] = [Extent2].[Company_Id]) AND ((CASE WHEN (([Exten t2].[FirstName] IS NULL) OR ((
CAST(LEN([Extent2].[FirstName]) AS int)) = 0)) TH EN
[Extent2].[LastName] ELSE [Extent2].[FirstName] + N' ' +
[Extent2].[LastName] END) = #p_linq_0) )
So the main idea to use .Wrap() method to convert from Expression world to non-expression which provide easy way to reuse expressions.
Let me know if you need more explanations.
I am developing a small framework to access the database. I want to add a feature that makes a query using a lambda expression. How do I do this?
public class TestModel
{
public int Id {get;set;}
public string Name {get;set;}
}
public class Repository<T>
{
// do something.
}
For example:
var repo = new Repository<TestModel>();
var query = repo.AsQueryable().Where(x => x.Name == "test");
// This query must be like this:
// SELECT * FROM testmodel WHERE name = 'test'
var list = query.ToDataSet();
// When I call ToDataSet(), it will get the dataset after running the made query.
Go on and create a LINQ Provider (I am sure you don't want to do this, anyway).
It's a lot of work, so maybe you just want to use NHibernate or Entity Framework or something like that.
If your queries are rather simple, maybe you don't need a full blown LINQ Provider. Have a look at Expression Trees (which are used by LINQ Providers).
You can hack something like this:
public static class QueryExtensions
{
public static IEnumerable<TSource> Where<TSource>(this Repo<TSource> source, Expression<Func<TSource, bool>> predicate)
{
// hacks all the way
dynamic operation = predicate.Body;
dynamic left = operation.Left;
dynamic right = operation.Right;
var ops = new Dictionary<ExpressionType, String>();
ops.Add(ExpressionType.Equal, "=");
ops.Add(ExpressionType.GreaterThan, ">");
// add all required operations here
// Instead of SELECT *, select all required fields, since you know the type
var q = String.Format("SELECT * FROM {0} WHERE {1} {2} {3}", typeof(TSource), left.Member.Name, ops[operation.NodeType], right.Value);
return source.RunQuery(q);
}
}
public class Repo<T>
{
internal IEnumerable<T> RunQuery(string query)
{
return new List<T>(); // run query here...
}
}
public class TestModel
{
public int Id { get; set; }
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
var repo = new Repo<TestModel>();
var result = repo.Where(e => e.Name == "test");
var result2 = repo.Where(e => e.Id > 200);
}
}
Please, don't use this as it is. This is just a quick and dirty example how expression trees can be analyzed to create SQL statements.
Why not just use Linq2Sql, NHibernate or EntityFramework...
if you want to do things like
db.Employee
.Where(e => e.Title == "Spectre")
.Set(e => e.Title, "Commander")
.Update();
or
db
.Into(db.Employee)
.Value(e => e.FirstName, "John")
.Value(e => e.LastName, "Shepard")
.Value(e => e.Title, "Spectre")
.Value(e => e.HireDate, () => Sql.CurrentTimestamp)
.Insert();
or
db.Employee
.Where(e => e.Title == "Spectre")
.Delete();
Then check out this, BLToolkit
You might want to look at http://iqtoolkit.codeplex.com/ Which is very complex and i dont recommend you to build something from scratch.
I just wrote something close to dkons's answer I will add it anyway. Just using fluent interface nothing more.
public class Query<T> where T : class
{
private Dictionary<string, string> _dictionary;
public Query()
{
_dictionary = new Dictionary<string, string>();
}
public Query<T> Eq(Expression<Func<T, string>> property)
{
AddOperator("Eq", property.Name);
return this;
}
public Query<T> StartsWith(Expression<Func<T, string>> property)
{
AddOperator("Sw", property.Name);
return this;
}
public Query<T> Like(Expression<Func<T, string>> property)
{
AddOperator("Like", property.Name);
return this;
}
private void AddOperator(string opName, string prop)
{
_dictionary.Add(opName,prop);
}
public void Run(T t )
{
//Extract props of T by reflection and Build query
}
}
Lets say you have a model like
class Model
{
public string Surname{ get; set; }
public string Name{ get; set; }
}
You can use this as :
static void Main(string[] args)
{
Model m = new Model() {Name = "n", Surname = "s"};
var q = new Query<Model>();
q.Eq(x => x.Name).Like(x=>x.Surname).Run(m);
}