Add starter code for chapter 8

No modifications for Complete folder yet.
This commit is contained in:
Alvin Ashcraft
2023-07-23 12:06:52 -04:00
parent 82078fd081
commit 21e22a0369
64 changed files with 3010 additions and 0 deletions
@@ -0,0 +1,175 @@
using MyMediaCollection.Enums;
using MyMediaCollection.Interfaces;
using MyMediaCollection.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyMediaCollection.Services
{
public class DataService : IDataService
{
private IList<MediaItem> _items;
private IList<ItemType> _itemTypes;
private IList<Medium> _mediums;
private IList<LocationType> _locationTypes;
public async Task InitializeDataAsync()
{
PopulateItemTypes();
PopulateMediums();
PopulateLocationTypes();
PopulateItems();
await Task.Delay(1);
}
private void PopulateItems()
{
var cd = new MediaItem
{
Id = 1,
Name = "Classical Favorites",
MediaType = ItemType.Music,
MediumInfo = _mediums.FirstOrDefault(m => m.Name == "CD"),
Location = LocationType.InCollection
};
var book = new MediaItem
{
Id = 2,
Name = "Classic Fairy Tales",
MediaType = ItemType.Book,
MediumInfo = _mediums.FirstOrDefault(m => m.Name == "Hardcover"),
Location = LocationType.InCollection
};
var bluRay = new MediaItem
{
Id = 3,
Name = "The Mummy",
MediaType = ItemType.Video,
MediumInfo = _mediums.FirstOrDefault(m => m.Name == "Blu Ray"),
Location = LocationType.InCollection
};
_items = new List<MediaItem>
{
cd,
book,
bluRay
};
}
private void PopulateMediums()
{
var cd = new Medium { Id = 1, MediaType = ItemType.Music, Name = "CD" };
var vinyl = new Medium { Id = 2, MediaType = ItemType.Music, Name = "Vinyl" };
var hardcover = new Medium { Id = 3, MediaType = ItemType.Book, Name = "Hardcover" };
var paperback = new Medium { Id = 4, MediaType = ItemType.Book, Name = "Paperback" };
var dvd = new Medium { Id = 5, MediaType = ItemType.Video, Name = "DVD" };
var bluRay = new Medium { Id = 6, MediaType = ItemType.Video, Name = "Blu Ray" };
_mediums = new List<Medium>
{
cd,
vinyl,
hardcover,
paperback,
dvd,
bluRay
};
}
private void PopulateItemTypes()
{
_itemTypes = new List<ItemType>
{
ItemType.Book,
ItemType.Music,
ItemType.Video
};
}
private void PopulateLocationTypes()
{
_locationTypes = new List<LocationType>
{
LocationType.InCollection,
LocationType.Loaned
};
}
public async Task<int> AddItemAsync(MediaItem item)
{
item.Id = _items.Max(i => i.Id) + 1;
_items.Add(item);
await Task.Delay(1);
return item.Id;
}
public async Task<MediaItem> GetItemAsync(int id)
{
await Task.Delay(1);
return _items.FirstOrDefault(i => i.Id == id);
}
public async Task<IList<MediaItem>> GetItemsAsync()
{
await Task.Delay(1);
return _items;
}
public IList<ItemType> GetItemTypes()
{
return _itemTypes;
}
public IList<Medium> GetMediums()
{
return _mediums;
}
public IList<Medium> GetMediums(ItemType itemType)
{
return _mediums
.Where(m => m.MediaType == itemType)
.ToList();
}
public IList<LocationType> GetLocationTypes()
{
return _locationTypes;
}
public async Task UpdateItemAsync(MediaItem item)
{
var idx = -1;
var matchedItem =
(from x in _items
let ind = idx++
where x.Id == item.Id
select ind).FirstOrDefault();
if (idx == -1)
{
throw new Exception("Unable to update item. Item not found in collection.");
}
_items[idx] = item;
await Task.Delay(1);
}
public async Task DeleteItemAsync(MediaItem item)
{
await Task.Delay(1);
throw new NotImplementedException();
}
public Medium GetMedium(string name)
{
return _mediums.FirstOrDefault(m => m.Name == name);
}
}
}
@@ -0,0 +1,84 @@
using Microsoft.UI.Xaml.Controls;
using MyMediaCollection.Interfaces;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace MyMediaCollection.Services
{
public class NavigationService : INavigationService
{
public NavigationService(Frame rootFrame)
{
AppFrame = rootFrame;
}
private readonly IDictionary<string, Type> _pages = new ConcurrentDictionary<string, Type>();
public const string RootPage = "(Root)";
public const string UnknownPage = "(Unknown)";
private static Frame AppFrame;
public void Configure(string page, Type type)
{
if (_pages.Values.Any(v => v == type))
{
throw new ArgumentException($"The {type.Name} view has already been registered under another name.");
}
_pages[page] = type;
}
/// <summary>
/// Gets the name of the currently displayed page.
/// </summary>
public string CurrentPage
{
get
{
var frame = AppFrame;
if (frame.BackStackDepth == 0)
return RootPage;
if (frame.Content == null)
return UnknownPage;
var type = frame.Content.GetType();
if (_pages.Values.All(v => v != type))
return UnknownPage;
var item = _pages.Single(i => i.Value == type);
return item.Key;
}
}
public void NavigateTo(string page)
{
NavigateTo(page, null);
}
public void NavigateTo(string page, object parameter)
{
if (!_pages.ContainsKey(page))
{
throw new ArgumentException($"Unable to find a page registered with the name {page}.");
}
AppFrame.Navigate(_pages[page], parameter);
}
public void GoBack()
{
if (AppFrame?.CanGoBack == true)
{
AppFrame.GoBack();
}
}
}
}
@@ -0,0 +1,300 @@
using Dapper;
using Dapper.Contrib.Extensions;
using Microsoft.Data.Sqlite;
using MyMediaCollection.Enums;
using MyMediaCollection.Interfaces;
using MyMediaCollection.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Storage;
namespace MyMediaCollection.Services
{
public class SqliteDataService : IDataService
{
private IList<ItemType> _itemTypes;
private IList<Medium> _mediums;
private IList<LocationType> _locationTypes;
private const string DbName = "mediaCollectionData.db";
private async Task<SqliteConnection> GetOpenConnectionAsync()
{
await ApplicationData.Current.LocalFolder.CreateFileAsync(DbName, CreationCollisionOption.OpenIfExists).AsTask();
string dbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, DbName);
var cn = new SqliteConnection($"Filename={dbPath}");
cn.Open();
return cn;
}
private async Task CreateMediumTableAsync(SqliteConnection db)
{
string tableCommand = @"CREATE TABLE IF NOT
EXISTS Mediums (Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name NVARCHAR(30) NOT NULL,
MediumType INTEGER NOT NULL)";
using var createTable = new SqliteCommand(tableCommand, db);
await createTable.ExecuteNonQueryAsync();
}
private async Task CreateMediaItemTableAsync(SqliteConnection db)
{
string tableCommand = @"CREATE TABLE IF NOT
EXISTS MediaItems (Id INTEGER PRIMARY KEY AUTOINCREMENT,
Name NVARCHAR(1000) NOT NULL,
ItemType INTEGER NOT NULL,
MediumId INTEGER NOT NULL,
LocationType INTEGER,
CONSTRAINT fk_mediums
FOREIGN KEY(MediumId)
REFERENCES Mediums(Id))";
using var createTable = new SqliteCommand(tableCommand, db);
await createTable.ExecuteNonQueryAsync();
}
private async Task InsertMediumAsync(SqliteConnection db, Medium medium)
{
//// IMPLEMENTATION WITHOUT DAPPER
//using var insertCommand = new SqliteCommand
//{
// Connection = db,
// CommandText = "INSERT INTO Mediums VALUES (NULL, @Name, @MediumType);"
//};
//insertCommand.Parameters.AddWithValue("@Name", medium.Name);
//insertCommand.Parameters.AddWithValue("@MediumType", (int)medium.MediaType);
//await insertCommand.ExecuteNonQueryAsync();
var newIds = await db.QueryAsync<long>(
$@"INSERT INTO Mediums
({nameof(medium.Name)}, MediumType)
VALUES
(@{nameof(medium.Name)}, @{nameof(medium.MediaType)});
SELECT last_insert_rowid()", medium);
medium.Id = (int)newIds.First();
}
private async Task<IList<Medium>> GetAllMediumsAsync(SqliteConnection db)
{
//// IMPLEMENTATION WITHOUT DAPPER
//IList<Medium> mediums = new List<Medium>();
//using var selectCommand = new SqliteCommand("SELECT Id, Name, MediumType FROM Mediums", db);
//using SqliteDataReader query = await selectCommand.ExecuteReaderAsync();
//while (query.Read())
//{
// var medium = new Medium
// {
// Id = query.GetInt32(0),
// Name = query.GetString(1),
// MediaType = (ItemType)query.GetInt32(2)
// };
// mediums.Add(medium);
//}
//return mediums;
var mediums =
await db.QueryAsync<Medium>(@"SELECT Id,
Name,
MediumType AS MediaType
FROM Mediums");
return mediums.ToList();
}
private async Task<List<MediaItem>> GetAllMediaItemsAsync(SqliteConnection db)
{
var itemsResult = await db.QueryAsync<MediaItem, Medium, MediaItem>
(
@"SELECT
[MediaItems].[Id],
[MediaItems].[Name],
[MediaItems].[ItemType] AS MediaType,
[MediaItems].[LocationType] AS Location,
[Mediums].[Id],
[Mediums].[Name],
[Mediums].[MediumType] AS MediaType
FROM
[MediaItems]
JOIN
[Mediums]
ON
[Mediums].[Id] = [MediaItems].[MediumId]",
(item, medium) =>
{
item.MediumInfo = medium;
return item;
}
);
return itemsResult.ToList();
}
private async Task<int> InsertMediaItemAsync(SqliteConnection db, MediaItem item)
{
var newIds = await db.QueryAsync<long>(
@"INSERT INTO MediaItems
(Name, ItemType, MediumId, LocationType)
VALUES
(@Name, @MediaType, @MediumId, @Location);
SELECT last_insert_rowid()", item);
return (int)newIds.First();
}
private async Task UpdateMediaItemAsync(SqliteConnection db, MediaItem item)
{
await db.QueryAsync(
@"UPDATE MediaItems
SET Name = @Name,
ItemType = @MediaType,
MediumId = @MediumId,
LocationType = @Location
WHERE Id = @Id;", item);
}
private async Task DeleteMediaItemAsync(SqliteConnection db, int id)
{
await db.DeleteAsync<MediaItem>(new MediaItem { Id = id });
}
private async Task PopulateMediumsAsync(SqliteConnection db)
{
_mediums = await GetAllMediumsAsync(db);
if (_mediums.Count == 0)
{
var cd = new Medium { Id = 1, MediaType = ItemType.Music, Name = "CD" };
var vinyl = new Medium { Id = 2, MediaType = ItemType.Music, Name = "Vinyl" };
var hardcover = new Medium { Id = 3, MediaType = ItemType.Book, Name = "Hardcover" };
var paperback = new Medium { Id = 4, MediaType = ItemType.Book, Name = "Paperback" };
var dvd = new Medium { Id = 5, MediaType = ItemType.Video, Name = "DVD" };
var bluRay = new Medium { Id = 6, MediaType = ItemType.Video, Name = "Blu Ray" };
var mediums = new List<Medium>
{
cd,
vinyl,
hardcover,
paperback,
dvd,
bluRay
};
foreach (var medium in mediums)
{
await InsertMediumAsync(db, medium);
}
_mediums = await GetAllMediumsAsync(db);
}
}
private void PopulateItemTypes()
{
_itemTypes = new List<ItemType>
{
ItemType.Book,
ItemType.Music,
ItemType.Video
};
}
private void PopulateLocationTypes()
{
_locationTypes = new List<LocationType>
{
LocationType.InCollection,
LocationType.Loaned
};
}
public async Task InitializeDataAsync()
{
using (var db = await GetOpenConnectionAsync())
{
await CreateMediumTableAsync(db);
await CreateMediaItemTableAsync(db);
PopulateItemTypes();
await PopulateMediumsAsync(db);
PopulateLocationTypes();
}
}
public async Task<int> AddItemAsync(MediaItem item)
{
using var db = await GetOpenConnectionAsync();
return await InsertMediaItemAsync(db, item);
}
public async Task<MediaItem> GetItemAsync(int id)
{
IList<MediaItem> mediaItems;
using var db = await GetOpenConnectionAsync();
mediaItems = await GetAllMediaItemsAsync(db);
//Filter the list to get the item for our Id
return mediaItems.FirstOrDefault(i => i.Id == id);
}
public async Task<IList<MediaItem>> GetItemsAsync()
{
using var db = await GetOpenConnectionAsync();
return await GetAllMediaItemsAsync(db);
}
public IList<ItemType> GetItemTypes()
{
return _itemTypes;
}
public IList<LocationType> GetLocationTypes()
{
return _locationTypes;
}
public Medium GetMedium(string name)
{
return _mediums.FirstOrDefault(m => m.Name == name);
}
public Medium GetMedium(int id)
{
return _mediums.FirstOrDefault(m => m.Id == id);
}
public IList<Medium> GetMediums()
{
return _mediums;
}
public IList<Medium> GetMediums(ItemType itemType)
{
return _mediums
.Where(m => m.MediaType == itemType)
.ToList();
}
public async Task UpdateItemAsync(MediaItem item)
{
using var db = await GetOpenConnectionAsync();
await UpdateMediaItemAsync(db, item);
}
public async Task DeleteItemAsync(MediaItem item)
{
using var db = await GetOpenConnectionAsync();
await DeleteMediaItemAsync(db, item.Id);
}
}
}