Travis
Travis

Reputation: 293

EF4.1 (Database First) Generic Repository: Problem with inconsistent data types

I am working on a new application which is using a legacy system's database. Each table in the database (there are about 600) has a 'Deleted' column to flag whether or not the item should be displayed to users. In my generic repository, I need to add LINQ expressions to filter out all items with Deleted == 1/True.

The problem I have ran into is that the "Deleted" column has different data types across tables.

It is a tinyint, smallint or bit in any given table. Theoretically, this should not be much of an issue since the data will always be stored as a 1 or a 0 (well, should be, I suppose, but either way a number of some sort) which can be cast to any of the specific types mentioned above. I'm just not sure how and/or where to go about casting this.

I created an interface which forces all of the entities to expose this property, but since the types are different, each entity with the different data types will cause issues. I was hoping (although already knew it wouldn't work) I could change the interface to "object" or "dynamic" which still causes compile time errors, since the EDMX model is creating the data model classes. I don't want to invest too much time in writing code in the T4 templates if that will not fix the issue.

When I change the EDMX model's entity properties to adhere to a specific datatype, I receive mapping errors ("Member Mapping specific is not valid. The type 'Edm.Byte[]' of member 'Deleted' in type 'MyEntity' is not compatible with 'SqlServer.bit[]' ....)

I doubt I'll be able to change the data types in the tables, since there are many different applications which use this database and I'm sure it will cause problems somewhere.

Has anyone else ran into a similar situation and come up with a working solution?

[EDIT] I'm going with the solution recommended by Baldy and creating a view to wrap the table and create an additional column which will be used to cast the column to a bit.

Upvotes: 1

Views: 628

Answers (3)

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364249

Generic approach is based on the fact that your entities share same behavior. In your case it means same property with the same type. Your entities don't fulfill this requirement and because of that you cannot use generic approach.

You must somehow inject generic behavior. What about this:

public interface IDeletable<TVal> where TVal : struct
{
    TVal Deleted { get; set; }
}

public class Entity : IDeletable<bool>
{
    public bool Deleted { get; set; }
    ...
}

public interface IDeletingStrategy<TEntity, TVal> 
    where TEntity : class, IDeletable<TVal>
    where TVal : struct
{
    void Delete(TEntity entity);
    IQueryable<TEntity> GetActive(IQueryable<TEntity> query);
}

public class Repository<TEntity, TVal> 
    where TEntity : class, IDeletable<TVal>
    where TVal : struct
{
   private IDeletingStrategy<TEntity,TVal> _deletingStrategy;

   public Repository(IDeletingStrategy<TEntity, TVal> deletingStrategy)
   {
       _deletingStrategy = deletingStrategy;
   }

   public void Delete(TEntity entity)
   {
       _deletingStrategy.Delete(entity);
       ...
   }

   public IQueryable<TEntity> GetActive()
   {
       return _deletingStrategy.GetActive(context.Set<TEntity>());
   }

}

public class BoolDeletingStrategy<TEntity> : IDeletingStrategy<TEntity, bool>
    where TEntity : class, IDeletable<bool>
{
    public void Delete(TEntity entity)
    {
        entity.Deleted = true;
    }

    public IQueryable<TEntity> GetActive(IQueryable<TEntity> query)
    {
        return query.Where(e => !e.Deleted);
    }
}

And you will instantiate your repository like:

var repo = new Repository<Entity, bool>(new BoolDeletingStrategy<Entity>());

I didn't test it but I guess it can work.

Upvotes: 1

Baldy
Baldy

Reputation: 3659

You may want to consider an ad-hoc task of converting the actual fields on the table with a T-SQL script.

Have you thought about that? is there any reason why you couldnt do it?

it may prove to be a good move further down the line...

Upvotes: 1

adolfojp
adolfojp

Reputation: 2991

Can you create a custom read only property in each model class using partial classes that reads the deleted bit and returns a uniform and consistent value?

Upvotes: 1

Related Questions