Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/aws-samples/legacy-cycle-store-mvc-app/llms.txt

Use this file to discover all available pages before exploring further.

The business layer sits between the Entity Framework data context and the MVC controllers, exposing a set of static manager classes that encapsulate all LINQ queries against the CYCLE_STORE database. Rather than having controllers reference CYCLE_STOREEntities directly, every data-access call is routed through CategoryManager or ProductManager. This keeps query logic in one place and gives controllers a clean, method-level API — a common and pragmatic pattern in legacy ASP.NET MVC applications built before the repository and unit-of-work patterns became standard practice.

Common

Common is a tiny infrastructure class whose sole job is to construct a CYCLE_STOREEntities instance on demand.
namespace AdventureWorks.Business
{
    public class Common
    {
        public static CYCLE_STOREEntities DataEntities
        {
            get { return new CYCLE_STOREEntities(); }
        }
    }
}
Every manager method that needs the database calls Common.DataEntities to obtain a context, performs its query, and then lets the context fall out of scope.
Common.DataEntities creates a brand-new CYCLE_STOREEntities instance on every property access — there is no shared, long-lived context. This means two calls to Common.DataEntities within the same request yield two separate DbContext objects. As a result, there is no unit-of-work scope: entities fetched in one call are not tracked in another, and change-tracking across multiple manager method calls is not supported. For a read-heavy catalogue application this is acceptable, but it would be a problem if any write operations needed to span multiple queries atomically.

CategoryManager

CategoryManager provides three static methods for retrieving category and subcategory data. All methods are in the AdventureWorks.Business namespace.

GetMainCategories

Returns every row in ProductCategory as a materialised list.
public static List<ProductCategory> GetMainCategories()
{
    var cats = from cat in Common.DataEntities.ProductCategories
               select cat;
    return cats.ToList();
}
Calling .ToList() executes the SQL query immediately and closes the DbContext before returning. Callers receive a plain List<ProductCategory> with no live EF tracking.

GetCategoryByName

Finds a single ProductCategory by its exact Name value. Returns null if no match is found.
public static ProductCategory GetCategoryByName(string name)
{
    var cats = from cat in Common.DataEntities.ProductCategories
               where cat.Name == name
               select cat;
    return cats.FirstOrDefault();
}
The comparison is case-sensitive at the C# level, though the actual sensitivity depends on the SQL Server collation of the Name column. Pass the name exactly as stored in the database (e.g., "Bikes", not "bikes").

GetProductSubcategoryByName

Finds a single ProductSubcategory by exact name match. Returns null if no match is found.
public static ProductSubcategory GetProductSubcategoryByName(string name)
{
    var cats = from cat in Common.DataEntities.ProductSubcategories
               where cat.Name == name
               select cat;
    return cats.FirstOrDefault();
}

ProductManager

ProductManager provides query methods for individual products and attribute-list helpers used to populate filter UIs. It operates on the same Common.DataEntities pattern as CategoryManager.
CategoryManager is declared in the AdventureWorks.Business namespace, while ProductManager is declared in the EpicAdventureWorks namespace — despite both classes residing in the same Business/ directory and using identical AdventureWorks.Business types. This namespace mismatch is a likely artifact of an incomplete rename or refactoring pass. Any code that references ProductManager must include a using EpicAdventureWorks; directive or use the fully-qualified name.

GetProductByName

Returns the first Product whose Name exactly matches the given string, or null.
public static Product GetProductByName(string name)
{
    var product = from p in Common.DataEntities.Products
                  where p.Name == name
                  select p;
    return product.FirstOrDefault();
}

GetProductByCategory

Returns an IQueryable<Product> filtered to products belonging to the given subcategory. Because it returns IQueryable, the query is not executed until the caller iterates the result — callers can append additional .Where or .OrderBy clauses before materialising.
public static IQueryable<Product> GetProductByCategory(ProductSubcategory category)
{
    IQueryable<Product> prodList = null;
    prodList = from p in Common.DataEntities.Products
               where p.ProductSubcategory.ProductSubcategoryID == category.ProductSubcategoryID
               select p;
    return prodList;
}

GetProductByProductId (two overloads)

The first overload uses Common.DataEntities to obtain a context automatically:
public static Product GetProductByProductId(int prodId)
{
    var prods = from p in Common.DataEntities.Product
                where p.ProductID == prodId
                select p;
    return prods.FirstOrDefault();
}
The second overload accepts an explicit Entities entities parameter, allowing the caller to supply an already-open context — useful when the caller needs the returned Product to remain tracked within an existing unit of work:
public static Product GetProductByProductId(int prodId, Entities entities)
{
    var prods = from p in entities.Product
                where p.ProductID == prodId
                select p;
    return prods.FirstOrDefault();
}

GetProductColor

Returns a deduplicated, alphabetically sorted list of non-null color values for all products in a given subcategory.
public static List<string> GetProductColor(int categoryId)
{
    colorList = (from p in Common.DataEntities.Product
                 where p.Color != null
                    && p.ProductSubcategory.ProductSubcategoryID == categoryId
                 orderby p.Color
                 select p.Color).Distinct().ToList();
    return colorList;
}
This is typically used to populate a color-filter dropdown on a product listing page.

GetProductWeight

Returns a deduplicated, ascending-sorted list of non-null weight values for all products in a given subcategory.
public static List<decimal?> GetProductWeight(int categoryId)
{
    weightList = (from p in Common.DataEntities.Product
                  where p.ProductSubcategory.ProductSubcategoryID == categoryId
                     && p.Weight != null
                  orderby p.Weight
                  select p.Weight).Distinct().ToList();
    return weightList;
}

GetProductSize

Returns a deduplicated, alphabetically sorted list of non-null size values for all products in a given subcategory.
public static List<string> GetProductSize(int categoryId)
{
    sizeList = (from p in Common.DataEntities.Product
                where p.Size != null
                   && p.ProductSubcategory.ProductSubcategoryID == categoryId
                orderby p.Size
                select p.Size).Distinct().ToList();
    return sizeList;
}

GetProductDesc

Fetches the description text for a given ProductDescriptionID from the ProductDescription table.
public static string GetProductDesc(int descId)
{
    var descList = from pd in Common.DataEntities.ProductDescription
                   where pd.ProductDescriptionID == descId
                   select pd.Description;
    if (descList != null) desc = descList.First();
    return desc;
}
Note that ProductDescription is not part of the three entities exposed on CYCLE_STOREEntities DbSets documented in the Data Model page — it is accessed through the EDMX-generated context which may expose additional sets beyond Products, ProductCategories, and ProductSubcategories.

Usage Example

The following example shows how a controller action would use the business layer to load navigation categories and then retrieve products for a selected subcategory:
// 1. Load all top-level categories for the navigation sidebar
List<ProductCategory> categories = CategoryManager.GetMainCategories();

// 2. Resolve a subcategory by name (e.g., from a URL segment)
ProductSubcategory subcat = CategoryManager.GetProductSubcategoryByName("Mountain Bikes");

if (subcat != null)
{
    // 3. Fetch products in that subcategory (deferred query)
    IQueryable<Product> products = ProductManager.GetProductByCategory(subcat);

    // 4. Materialise with optional client-side ordering
    List<Product> productList = products.OrderBy(p => p.ListPrice).ToList();

    // 5. Build filter lists for the sidebar
    List<string>   colors  = ProductManager.GetProductColor(subcat.ProductSubcategoryID);
    List<string>   sizes   = ProductManager.GetProductSize(subcat.ProductSubcategoryID);
    List<decimal?> weights = ProductManager.GetProductWeight(subcat.ProductSubcategoryID);
}
Each call to Common.DataEntities opens a new connection and DbContext. For a listing page that calls GetMainCategories, GetProductByCategory, GetProductColor, GetProductSize, and GetProductWeight, that is five separate DbContext instances and five database round-trips.

Build docs developers (and LLMs) love