TyForHelpDude
TyForHelpDude

Reputation: 5001

decide entity type programmatically in .net entity framework 6

I have a method updating certain record with id, and there is some entities have same structure with that table so I wonder how can I do something like below;

    public void deleteCarwithId(int id, int type)
            {
                string[] brands = { "BMW", "VOLKSWAGEN", "RENAULT", "FIAT" };
                T entity = Convert.ToEntity(brands[type]);//ofc there is no such a method yet
                var result =UnitOfWork.Repository<entity>().FirstOrDefault(u => u.ID == id);
                result.IsDeleted = true;
                Update(result);
            }

instead this(it works but ugly);

public void deleteCarwithId(int id, int type)
    {
        string[] brands = { "BMW", "VOLKSWAGEN", "RENAULT", "FIAT" };
        if (brands[type] == "BMW")
        {
            var result = UnitOfWork.Repository<BMW>().FirstOrDefault(u => u.ID == id);
            result.IsDeleted = true;
            Update(result);
        }
        if (brands[type] == "VOLKSWAGEN")
        {
            var result = UnitOfWork.Repository<VOLKSWAGEN>().FirstOrDefault(u => u.ID == id);
            result.IsDeleted = true;
            Update(result);
        }
    }

Upvotes: 0

Views: 35

Answers (1)

ASpirin
ASpirin

Reputation: 3651

Easiest way to achieve this is using reflection and MakeGenericMethod function:

1st: create an interface for types you want to delete in future:

public interface IDeletable
{
    bool IsDeleted { get; set; }
    int Id { get; set; }
}

2nd separate a logic function based on created interface structure

public void Delete<T>(UnitOfWork unitOfWork, int id) where T: IDeletable
{
    var repository = (Repository<T>)typeof(UnitOfWork).GetMethod("Repository")
        .MakeGenericMethod(typeof(T)).Invoke(new UnitOfWork(), new object[0]);
    var item = repository.FirstOrDefault(x => x.Id == id);
    item.IsDeleted = true;
    Update(item);
}

3rd call the function with specified type

public void deleteCarwithId(int id, int type)
{
    var method = typeof(Program).GetMethod("Delete"); // Binding parameters could requires
    switch(type)
    {
        case 0: method.MakeGenericMethod(typeof(BMW))
                .Invoke(this, new object[]{unitOfWork, id});
                return;
        ...
    }
}

As alternative to reflection, can be used a dictionary of repositories: Assuming that 1st step from above has been done and that your repository is IQueryable, than the method can looks like:

public void deleteCarwithId(int id, int type)
{
    var source = new Dictionary<int, IQueryable<IDeletable>>
    {
        {0, unitOfWork.Repository<BMW>() }
        // all other types
    };
    var repository = source[i];
    var item = repository.FirstOrDefault(x => x.Id == id);
    item.IsDeleted = true;
    Update(item);
}

Of course, to reduce amount of unnecessary initializations, the Dictionary can be created as a field in the hosting object or even as a static field. In case of static field repositories will be never collected by GC.

Upvotes: 1

Related Questions