Alex Gordon
Alex Gordon

Reputation: 60821

how to return a loosely-typed object?

How do we avoid breaking changes in a controller method, when the database schema changes?

Suppose I am returning an object:

public class Bike
{
   public int Wheels {get;}
   public int Id {get;}
}

in the following controller:

public class BikeController
{
    [HttpGet]
    public List<Bike> Get([FromBody] MyRequest request)
    {
        var context = new DbContext(_repository.Database.Connection.ConnectionString);
        var procedure = request;
        return context.Database.ExecuteStoredProcedure<Bike>(procedure).ToList();
    }
}

At some point, the database code changes. I don't want to have to redefine the Bike schema in C#.

How do we change the signature of the Bike controller method, in order to not have any breaking changes, when the database schema changes?

I'm looking for something like the following:

public IHttpActionResult Get()
{
    var context = new DbContext(_repository.Database.Connection.ConnectionString);
    var procedure = request;
    return context.Database.ExecuteStoredProcedure<object>(procedure).ToList();
}

Upvotes: 1

Views: 264

Answers (4)

Rickless
Rickless

Reputation: 1455

As long as you don't access any property or use any method its existence is dependent on a schema object or anything related to the database You are on the safe side. Making the controller agnostic to the database schema, will make it very unlikely that this controller will be changed due to changes on the database side, and that's why the Data Access layers are made. I think if we applied separation of concerns principle we would see that it is not the Controller responsibility to deal with the database, this must be done through some kinds of Brokers like a repository interface type injected into the controller constructor. The controller will just see insert, update, delete methods but it doesn't have any knowledge about the database. Also, it's not a loosely-typed object. It's a loosely coupled types what you really need.

Upvotes: 1

Fakhar Ahmad Rasul
Fakhar Ahmad Rasul

Reputation: 1691

You are simply retrieving an object from the database, the number of properties which comes inside the object wont effect or break your ActionMethod.

If you are still worried for a reason like the properties inside your object are not what you want to render on the view then you can use a ViewModel and use your Bike objects properties to populate the viewmodel and render the viewmodel instead.

Upvotes: 1

Rahul
Rahul

Reputation: 77896

I don't see why your controller at all need to change since you are just returning the retrieved type directly without referring any of it's properties in your action method.

Moreover, why you are calling .ToList() when you are returning a single Bike object. Further more, you may consider using a Model or ViewModel instead of returning the entity directly as an option.

@Evk already pointed that a newly added property would just get lost while deserializing but if you want to return a abstract object then you can have all your entity inherits from a BaseEntity having common property and return that instead like

BaseEntity obj = context.Database.ExecuteStoredProcedure<Bike>(procedure);
returb obj;

Upvotes: 3

NetMage
NetMage

Reputation: 26926

I think you have a few alternatives:

  1. Return dynamic instead of Bike. However, this has a performance impact on all users of the dynamic objects.

  2. Return object instead of Bike.

But in both cases your Bike stored procedure will still return the updated data which won't be compatible with the Bike object, so you will still need to recompile the controller.

  1. Return a standard object that represents the BikeController response and matches the stored procedures response.

Consider how you handle database updates in SQL - your SELECT statement specifies the exact columns you need and is unaffected by schema changes that don't affect the returned columns, or if you are using * you ignore any columns you don't need, which isn't conducive to strong typing or ORMs.

Upvotes: 1

Related Questions