0

I have written a small application using ASP.NET Core to create and manage collections of cards for a collectable card game. I currently have a version that successfully downloads bulk card data via API call, parses the JSON response, and loads it into local SQL Server database. I then use the local data to add the cards to the collections (through the UI or via CSV import), lookup prices, etc. As an academic exercise, I'm deliberately overcomplicating the design of this as if it were a large scale enterprise application since I really have no reason to build it other than to learn more about programming, so I'm wondering about best practices for something like this?

Currently I have the application broken into four projects: an API client for pulling the card data from the external API, a data access/domain layer using EF Core and SQL server, a service layer that orchestrates everything, and a Blazor Server UI. The main thing that I'm struggling with is that my service layer is dependent on both the API client and the DBContext, so I'm wondering if there's a good way to consolidate the dependencies, since the data from both sources are mapped to the same domain objects.

From what I've been reading, it seems like setting up a repository would be a good option and is common when there are multiple data sources being utilized. I have a 2nd version with repositories for accessing the local database but I'm not sure how to introduce the external API calls into this version. I think I could create separate implementations of the Card Repository Interface, one to access my local SQL database and another to access the external API but I'm not sure how the application would know when I need one or the other if I'm using dependency injection.

For example, periodically I want to check for updated card data from the external API and update my database with the new data, but for the most part I'll be reading the card data from the local database for managing the collections. Any advice on how to approach this? I can give code examples if needed. Thanks.

2
  • lease don't cross-post: stackoverflow.com/questions/64841534/… "Cross-posting is frowned upon as it leads to fragmented answers splattered all over the network..."
    – gnat
    Nov 15, 2020 at 14:38
  • I was told over there that this site was a more appropriate place to ask my question, so I asked here. What is the appropriate protocol here? I've been searching like crazy for examples similar to mine and cannot find anything that addresses my question on an appropriate approach for this, so I'm just hoping for some advice.
    – DogoPilot
    Nov 15, 2020 at 14:43

1 Answer 1

1

Best practice to seperate Definition from Implementation would be to have a project just containing your interfaces, your domain-model and domain-logic. And then other projects implementing he interfaces with whatever dependency they have.

In your case, having an "Adapter" that translates one datatype (API) to another (Database) you have to use an common class that is understood by both of your participants.

Example:

C#, but can be applied to any OOP-language

Core-Project:

class TradingCard {
    public string Title {get;set;}
    public decimal Price {get;set;}
}

interface ICardSource {
    TradingCard[] LoadCards();
} 

interface ICardSink {
    void StoreCards(TradingCard[]);
} 

API-Project:

references Core-Project

class TradingCardDTO {
    public WeirdTitleProperty {get;set;}
    public int PriceInDollar { get;set;}
}

class CardSourceXYZAPI : ICardSource {
    TradingCard[] LoadCards() {
        // all the logic for reading the api
        // AND translating TradingCardDTO to TradingCard
    }
}

DB-Project:

references Core-Project

class TradingCardEntity {
    [Key]
    public Id {get;set;}
    public MyTitle {get;set;}
    public float UnitPrice { get;set;}
}

class CardSinkEFCore : ICardSink {
    void StoreCards(TradingCard[]) {
        // translate TradingCard to TradingCardEntity
        // logic for writing to the DB
    }
}

Main-Application (mostly the GUI or API the Enduser consumes)

  • references Core-Project
  • references API-Project
  • references DB-Project

You use your concrete Implementations here. Maybe use DI to inject them. Here orchestration should occur. Logic that's purely domain-related (e.g. checking some values on your card-collections) should occur in the Core-Project, not here.

Here you would connect the api and the db:

ICardSource api = new CardSourceXYZAPI("...options...");
ICardSink db = new CardSinkEFCore("...options...");

db.StoreCards(api.LoadCards());

And yes, your Main-App has to have all dependencies like API-Lib, EFCore, etc., but you could have different Applications, they are just the "Configuration"/"Orchestration", all real logic is in the other projects.

Just as a Side-Note - your DB-Project can of course implement the ICardSource too, so you can use this too in your Main-Application, without needing to know if the Cards come from the API or the DB or whatever (Dummy-List for testing)

1
  • Thanks, I appreciate the response! I am still trying to absorb it all but I will take this input into consideration.
    – DogoPilot
    Nov 18, 2020 at 23:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.