Automatically trim white space from columns when mapping with Dapper - c#

I'm using Dapper to hit a legacy database and there's whitespace padding on the column.
The solution I've found is to add properties like:
private string _status;
public string status
{
get { return _status; }
set { _status = value.Trim(); }
}
Obviously this is tedious to do on every string member of every model that will interact with this database. According to the MSDN Entry on SET ANSI_PADDING, modifying this to OFF isn't an option either.
As the database is not mine, I'm unable to change it to nvarchar or simiar.
Is there an easy way to force Dapper to trim every string column that it reads from the database?

Take a look at Dapper.Contrib. The Get method can generate a change tracking proxy over each returned instance if it is an interface type.
(From the comments for the Get method)
Returns a single entity by a single id from table "Ts". T must be of interface type.
Id must be marked with [Key] attribute.
Created entity is tracked/intercepted for changes and used by the Update() extension.
You could look to modify the CreateProperty method to implement your Trim logic

One way is to write an extension method and use reflection to trim all string properties on the class. For example:
public static class ObjExt
{
public static void Trim<T>(this T item)
{
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var p in properties)
{
if (p.PropertyType != typeof(string) || !p.CanWrite || !p.CanRead) { continue; }
var value = p.GetValue(item) as string;
p.SetValue(item,value.Trim());
}
}
}

Related

C# Entity Framework Custom Constraint

I am currently trying to make a custom constraint with the C# Entity Framework. In more detail:
I have a number field which only can have certain values (for example 1, 2 and 3). How do I achieve this constraint in a code first environment?
Entity Framework automatically validates any validations you add to your model by ValidationAttributes. RequiredAttribute or RangeAttribute are two examples of built-in subclasses of this attribute.
If you want some custom validation, the most convenient way is to piggyback on this mechanism and create you own ValidationAttribute subclass.
If you want to validate a non-contiguous range of values you can't use RangeAttribute but you could make an own attribute, for instance like this:
public class AllowedValuesAttribute : ValidationAttribute
{
private readonly ICollection<object> _validValues;
private readonly Type _type;
public AllowedValuesAttribute(Type type, object[] validValues)
{
_type = type;
_validValues = validValues.Where(v => v != null && v.GetType() == type).ToList();
}
public override bool IsValid(object value)
{
return value.GetType() == _type && _validValues.Contains(value);
}
public override string FormatErrorMessage(string name)
{
return string.Format("Value for '{0}' is not an allowed value", name);
}
}
Usage:
[AllowedValues(typeof(int), new object[] { 1, 2, 4, 8, 16 })]
public int Base { get; set; }
Note that we have to use fixed values here, because the content of the attribute must be known at compile time. Also, we have to use object because (currently) C# doesn't support generic attributes. Apart from that, there are numerous options. For example, the attribute could also have a method that finds allowed values at runtime, maybe from a named source, so you can supply this name in its constructor.
I don't see any problem in adorning entity classes with validation attributes. The entity model is not a domain model, it's part of a data access layer. It's primary purpose is (and should be) to facilitate an application's data access. If an entity model also happens to support business logic that's a mere bonus.
It's very bad practice to add dataannotations in domain-model, like D.Mac wrote.
So what about doing it the nicer way?
public MyClass
{
private int myNumberField;
public int MyNumberField
{
get { return myNumberField; }
set
{
if (value >= 1 && value <=3)
myNumberField = value;
else
// throw exception?
// set default-value (maybe 1)?
// do nothing?
}
}
}
you could do whatever you want in the setter of your property
and only restricting it in the front-end is not the best solution, since you always can modify javascript/html - but you should show the user, that he only can insert values 1, 2 or 3.
Also restrict it in the viewmodel with data annotations.
OR:
you could also override EntityFrameworks SaveChanges and add your businesslogic:
public override int SaveChanges(SaveOptions options)
{
foreach (ObjectStateEntry entry in
ObjectStateManager.GetObjectStateEntries(
EntityState.Added | EntityState.Modified))
{
// Validate the objects in the Added and Modified state
// if the validation fails, e.g. throw an exeption.
}
return base.SaveChanges(options);
}

Select property by lambda by PropertyInfo variable

This is my POCO object:
public class ExampleTestOfDataTypes
{
public float FloatProp { get; set; }
public BoolWrapper BoolProp2 { get; set; }
}
This is configuration file of the POCO
public class ExampleTestOfDataTypesConfig : EntityTypeConfiguration<ExampleTestOfDataTypes>
{
public ExampleTestOfDataTypesConfig()
{
this.Property(x=>x.FloatProp).HasColumnName("CustomColumnName");
}
}
This is definition of EntityTypeConfiguration (the property configuration is just for example)
ExampleTestOfDataTypesConfig config = new ExampleTestOfDataTypesConfig();
I need to go through all the properties of class ExampleTestOfDataTypes, find all the properties which dataTypes are derived from Wrapper (BoolWrapper is) and then get these properties using lambda expression. Or anyhow select them by config.Property(...)
Type configPocoType = config.GetType().BaseType.GetGenericArguments()[0];
var poco = Activator.CreateInstance(configPocoType);
foreach (System.Reflection.PropertyInfo property in poco.GetType().GetProperties())
{
if (property.PropertyType.BaseType!=null&&
property.PropertyType.BaseType == typeof(Wrapper)
)
{
//TODO: Set property
//config.Property(x=>x.[What here]); //?
}
}
Thanks
Update
I didn't notice that the Property method is not your own implementation, sorry. It looks like you have to create an expression manually. This should work, or at least be close enough:
var parameter = Expression.Parameter(configPocoType);
var lambda = Expression.Lambda(
Expression.MakeMemberAccess(parameter, property),
parameter);
config.Property(lambda);
Original answer
It looks pretty likely that your existing Property method just uses an Expression to read the name of the property while maintaining compile-time safety. Most of the time such methods use reflection to pull out the property name into a string and then go on reflecting using the string name (possibly by calling another overload of Property that accepts a string).
Therefore, a reasonable approach is to invoke this other overload yourself, since your code already has a PropertyInfo in hand from which you can immediately get the property name.
If you only have one Property method, refactor by splitting it into two parts: one that pulls the name out of the Expression and one that works with the name; you can then call the second directly from your code.

LINQ Changes Not Recognized When Using Generics

I am currently trying to create a Class which employs generics in order to reduce the amount of work needed for future development. As I add Tables to the LINQ To SQL Designer, certain basic Methods are used in each one. Rather than reproduce them in every Partial Class associated with every new Table, I would like to employ a single generic Class. The issue is that any changes made to the Entities are not recognized and therefore not submitted.
Public Partial Class ABC
{
Public Static Bool Synchronize(string source, string destination)
{
try
{
DataContext destinationDB = DataConnection.Destination(destination);
Table<ABC> destinationABCs = destinationDB.ABCs;
DataContext sourceDB = DataConnection.Destination(source)
Table<ABC> sourceABCs = sourceDB.ABCs;
foreach (ABC ABCCode in sourceABCs)
{
ABC destABCCode = destinationABCs.SingleOrDefault(x => x.Id == ABCCode.Id);
bool same = EntityProcessing.AreIdentical(ABCCode, destABCCode);
if (same == false)
{
destABCCode = (ABC)EntityProcessing.Synchronize(ABCCode, destABCCode);
}
}
ChangeSet test = destinationDB.GetChangeSet(); // Test Line For Debugging
destinationDB.SubmitChanges();
}
return true;
}
}
The next Class is:
Public Static Class EntityProcessing
{
Public Static Bool AreIdentical(Object sourceEntity, Object destinationEntity)
{
if (sourceEntity.GetType() == destinationEntity.GetType())
{
Type t = sourceEntity.GetType();
FieldInfo[] tList = t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo fi in tList)
{
if ((fi.GetValue(sourceEntity) != null ? fi.GetValue(sourceEntity).ToString()
: null) == (fi.GetValue(destinationEntity) != null ?
fi.GetValue(destinationEntity).ToString() : null))
{ continue; }
else
{ return false; }
}
return true;
}
else
{ return false; }
}
Public Static Object Synchronize(Object sourceEntity, Object destinationEntity)
{
if (sourceEntity.GetType() == destinationEntity.GetType())
{
Type t = sourceEntity.GetType();
FieldInfo[] tList = t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo fi in tList)
{
fi.SetValue(destinationEntity, fi.GetValue(sourceEntity));
}
}
return destinationEntity;
}
}
I have tried modifying the EntityProcessing.Synchronize method into a Void method as well. Neither works. Both will return the correct Entity with the Fields set to the appropriate results. The issue lies in the fact that LINQ does not recognize the Entities as having changed.
If I add a temporary line of ChangeSet test = destinationDB.GetChangeSet();, the Updated count is zero. The loss appears to be in the conversion to Objects.
I have tried setting the Parameter Type to ABC on the EntityProcessing.Synchronize() method and modifying a Field, and the Updated count in test is correct. How do I resolve this?
How do I submit the updated entities to the database or rather, how do I get LINQ to recognize these entities are being changed and needing an update?
Do you mean: Public Static Bool Synchronize<ABC>(string source, string destination) with "ABC" as the generic type?
However, I don't think your .ABCs will work that simply. You may have to use reflection to get at the proeprty with that particular name. For example, first use reflection to get the name of the type parameter (ABC), and then use reflection to get the table field from the data source based on this type name.

Using reflection to address a Linqed property

I'm trying to writing a generic method that will load a record of a specific type, with a specific ID. Here's one way that works:
public abstract class LinqedTable<T> where T : LinqableTable {
public static T Get(long ID) {
DataContext context = LinqUtils.GetDataContext<T>();
var q = from obj in context.GetTable<T>()
where obj.ID == ID
select obj;
return q.Single<T>();
}
}
public abstract class LinqableTable {
public abstract long ID { get; set; }
}
You can ignore the call to LinqUtils.GetDataContext<T>(); that's a utility function I've got to deal with the fact that I have multiple data contexts in my program. The point is that now I can declare any of my classes as subclasses of LinqableTable, and I can easily instantiate a record of that table just by calling LinqedTable<MyType>.Get(ID).
This has some limitations, however. Firstly, it forces all of my tables to have an I
identity field of type long, named ID. Secondly, because I'm using an abstract method, I am forced to go to the O/R designer and change the inheritance property of every ID field in my system to "override".
I want more flexibility than that. So naturally, I tried reflection, and came out with the following:
public abstract class LinqedTable<T> where T : LinqableTable {
public static T Get(long ID) {
DataContext context = LinqUtils.GetDataContext<T>();
var q = from obj in context.GetTable<T>()
where obj.IDValue == ID
select obj;
return q.Single<T>();
}
}
public abstract class LinqableTable {
internal long IDValue {
get { return (long)IDProperty.GetValue(this, null); }
set { IDProperty.SetValue(this, value, null); }
}
internal PropertyInfo IDProperty {
get { return this.GetType().GetProperty(IDPropertyName); }
}
internal protected virtual string IDPropertyName {
get { return "ID"; }
}
}
Theoretically, this allows me to override the ID column name, the cast to long should be OK with any integral data type, and I don't need to go defining all my ID columns as overrides.
BUT
Linq doesn't like this. On the call to q.Single<T>(); I get a runtime error:
The member 'EISS.Utils.LinqableTable.IDValue' has no supported translation to SQL.
OK, today I learned that Linq does some kind of magic on the back end; it doesn't instantiate obj and just read the IDValue property. So must be there's some attribute that needs to be set on the IDValue property that lets Linq do its thing.
But what?
Linq to SQL tries to translate your linq-query into SQL, but it does not know how to translate your property to a column name in the DB.
A good explanation can be found here on SO:
simple linq to sql has no supported translation to SQL
But how to solve it, is another matter. I have with succes used the apporoach from this thread:
http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/df9dba6e-4615-478d-9d8a-9fd80c941ea2/
Or you can use dynamic query as mentioned here by scott guthrie:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Having read these posts: Generic Data Access using LINQ to SQL and C#,
LINQ-to-SQL: Generic Primary Key function and
Calling a generic method with Type
My colleague and I came up with the following digest:
We added the following method to our datacontext (in a partial class).
public T GetInstanceByPrimaryKey<T>(object primaryKeyValue) where T : class
{
var table = this.GetTable<T>();
var mapping = this.Mapping.GetTable(typeof(T));
var pkfield = mapping.RowType.DataMembers.SingleOrDefault(d => d.IsPrimaryKey);
if (pkfield == null)
throw new Exception(String.Format("Table {0} does not contain a Primary Key field", mapping.TableName));
var param = Expression.Parameter(typeof(T), "e");
var predicate =
Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(param, pkfield.Name), Expression.Constant(primaryKeyValue)), param);
return table.SingleOrDefault(predicate);
}
Then, where we need to instanciate from the type name and primary key value:
string name = "LinqObjectName";
int primaryKey = 123;
var dc = new YourDataContext();
Type dcType = dc.GetType();
Type type = dcType.Assembly.GetType(String.Format("{0}.{1}", dcType.Namespace, name));
MethodInfo methodInfoOfMethodToExcute = dc.GetType().GetMethod("GetInstanceByPrimaryKey");
MethodInfo methodInfoOfTypeToGet = methodInfoOfMethodToExcute.MakeGenericMethod(name);
var instance = methodInfoOfTypeToGet.Invoke(dc, new object[] { primaryKey });
return instance;
Hope this helps!
Since LINQ statements referred to a LINQ-to-SQL IQueryable are translated to SQL queries, you will have to use the AsEnumerable extension (which will in turn cause a read of all the items in the database) and do reflection-related stuff on that IEnumerable.
EDIT
As required here's a clarificationAs specified in a comment, what I meant was something like:
(from obj in context.GetTable<T>() select obj).AsEnumerable().Where(x => x.IDValue == ID)
Unlike a query executed on an IQueryable, which can be perfectly translated to SQL such as
context.GetTable().Where(x => x.Text == "Hello")
which gets converted to something similar to
SELECT * FROM TABLE_MAPPED_TO_TYPE_T WHERE Text = 'Hello'
a query executed against an IEnumerable - in your case - will be executed by fetching all the entries of your table and then applying code-wise the specified filter.

C# setting property values through reflection with attributes

I am trying to build an object through an attribute on a classes property that specifies a column in a supplied data row that is the value of the property, as below:
[StoredDataValue("guid")]
public string Guid { get; protected set; }
[StoredDataValue("PrograGuid")]
public string ProgramGuid { get; protected set; }
In a Build() method on a base object, I am getting the attribute values set on these properties as
MemberInfo info = GetType();
object[] properties = info.GetCustomAttributes(true);
However, at this point I am realising the limitation in my knowledge.
For a start, I don't appear to be getting back the correct attributes.
And how do I set these properties through reflection, now that I have the attributes? Am I doing / thinking something fundamentally incorrect?
There are a couple of separate issues here
typeof(MyClass).GetCustomAttributes(bool) (or GetType().GetCustomAttributes(bool)) returns the attributes on the class itself, not the attributes on members. You will have to invoke typeof(MyClass).GetProperties() to get a list of properties in the class, and then check each of them.
Once you got the property, I think you should use Attribute.GetCustomAttribute() instead of MemberInfo.GetGustomAttributes() since you exactly know what attribute you are looking for.
Here's a little code snippet to help you start:
PropertyInfo[] properties = typeof(MyClass).GetProperties();
foreach(PropertyInfo property in properties)
{
StoredDataValueAttribute attribute =
Attribute.GetCustomAttribute(property, typeof(StoredDataValueAttribute)) as StoredDataValueAttribute;
if (attribute != null) // This property has a StoredDataValueAttribute
{
property.SetValue(instanceOfMyClass, attribute.DataValue, null); // null means no indexes
}
}
EDIT: Don't forget that Type.GetProperties() only returns public properties by default. You will have to use Type.GetProperties(BindingFlags) to get other sorts of properties as well.

Categories

Resources