mirror of
https://github.com/markjprice/cs11dotnet7.git
synced 2026-04-06 14:53:47 +00:00
Initial commit
This commit is contained in:
parent
01d6ccf414
commit
dd097904c2
54 changed files with 37154 additions and 0 deletions
24
vscode/Chapter10/Ch10Ex02DataSerialization/Category.cs
Normal file
24
vscode/Chapter10/Ch10Ex02DataSerialization/Category.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema; // [Column]
|
||||
|
||||
namespace Packt.Shared;
|
||||
|
||||
public class Category
|
||||
{
|
||||
// these properties map to columns in the database
|
||||
public int CategoryId { get; set; }
|
||||
|
||||
public string? CategoryName { get; set; }
|
||||
|
||||
[Column(TypeName = "ntext")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
// defines a navigation property for related rows
|
||||
public virtual ICollection<Product> Products { get; set; }
|
||||
|
||||
public Category()
|
||||
{
|
||||
// to enable developers to add products to a Category we must
|
||||
// initialize the navigation property to an empty collection
|
||||
Products = new HashSet<Product>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0-*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Northwind.db">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
47
vscode/Chapter10/Ch10Ex02DataSerialization/Northwind.cs
Normal file
47
vscode/Chapter10/Ch10Ex02DataSerialization/Northwind.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using Microsoft.EntityFrameworkCore; // DbContext, DbContextOptionsBuilder
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
|
||||
namespace Packt.Shared;
|
||||
|
||||
// this manages the connection to the database
|
||||
public class Northwind : DbContext
|
||||
{
|
||||
// these properties map to tables in the database
|
||||
public DbSet<Category>? Categories { get; set; }
|
||||
public DbSet<Product>? Products { get; set; }
|
||||
|
||||
protected override void OnConfiguring(
|
||||
DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
string path = Path.Combine(
|
||||
Environment.CurrentDirectory, "Northwind.db");
|
||||
|
||||
string connection = $"Filename={path}";
|
||||
|
||||
ConsoleColor previousColor = ForegroundColor;
|
||||
ForegroundColor = ConsoleColor.DarkYellow;
|
||||
WriteLine($"Connection: {connection}");
|
||||
ForegroundColor = previousColor;
|
||||
|
||||
optionsBuilder.UseSqlite(connection);
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(
|
||||
ModelBuilder modelBuilder)
|
||||
{
|
||||
// example of using Fluent API instead of attributes
|
||||
// to limit the length of a category name to 15
|
||||
modelBuilder.Entity<Category>()
|
||||
.Property(category => category.CategoryName)
|
||||
.IsRequired() // NOT NULL
|
||||
.HasMaxLength(15);
|
||||
|
||||
if (Database.ProviderName?.Contains("Sqlite") ?? false)
|
||||
{
|
||||
// added to "fix" the lack of decimal support in SQLite
|
||||
modelBuilder.Entity<Product>()
|
||||
.Property(product => product.Cost)
|
||||
.HasConversion<double>();
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
vscode/Chapter10/Ch10Ex02DataSerialization/Northwind.db
Normal file
BIN
vscode/Chapter10/Ch10Ex02DataSerialization/Northwind.db
Normal file
Binary file not shown.
8722
vscode/Chapter10/Ch10Ex02DataSerialization/Northwind4SQLite.sql
Normal file
8722
vscode/Chapter10/Ch10Ex02DataSerialization/Northwind4SQLite.sql
Normal file
File diff suppressed because it is too large
Load diff
26
vscode/Chapter10/Ch10Ex02DataSerialization/Product.cs
Normal file
26
vscode/Chapter10/Ch10Ex02DataSerialization/Product.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using System.ComponentModel.DataAnnotations; // [Required], [StringLength]
|
||||
using System.ComponentModel.DataAnnotations.Schema; // [Column]
|
||||
|
||||
namespace Packt.Shared;
|
||||
|
||||
public class Product
|
||||
{
|
||||
public int ProductId { get; set; } // primary key
|
||||
|
||||
[Required]
|
||||
[StringLength(40)]
|
||||
public string ProductName { get; set; } = null!;
|
||||
|
||||
[Column("UnitPrice", TypeName = "money")]
|
||||
public decimal? Cost { get; set; } // property name != column name
|
||||
|
||||
[Column("UnitsInStock")]
|
||||
public short? Stock { get; set; }
|
||||
|
||||
public bool Discontinued { get; set; }
|
||||
|
||||
// these two define the foreign key relationship
|
||||
// to the Categories table
|
||||
public int CategoryId { get; set; }
|
||||
public virtual Category Category { get; set; } = null!;
|
||||
}
|
||||
163
vscode/Chapter10/Ch10Ex02DataSerialization/Program.Functions.cs
Normal file
163
vscode/Chapter10/Ch10Ex02DataSerialization/Program.Functions.cs
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
using System.Xml; // XmlWriter
|
||||
using System.Text.Json; // Utf8JsonWriter, JsonWriterOptions
|
||||
using Packt.Shared; // Category, Product
|
||||
|
||||
using static System.IO.Path;
|
||||
using static System.Environment;
|
||||
|
||||
// we want to easily show the difference between outputting
|
||||
// XML using elements or attributes so we will define a
|
||||
// delegate to reference the two different methods.
|
||||
|
||||
delegate void WriteDataDelegate(string name, string? value);
|
||||
|
||||
partial class Program
|
||||
{
|
||||
static void GenerateXmlFile(
|
||||
IQueryable<Category> categories, bool useAttributes = true)
|
||||
{
|
||||
string which = useAttributes ? "attibutes" : "elements";
|
||||
|
||||
string xmlFile = $"categories-and-products-using-{which}.xml";
|
||||
|
||||
using (FileStream xmlStream = File.Create(
|
||||
Combine(CurrentDirectory, xmlFile)))
|
||||
{
|
||||
using (XmlWriter xml = XmlWriter.Create(xmlStream,
|
||||
new XmlWriterSettings { Indent = true }))
|
||||
{
|
||||
|
||||
WriteDataDelegate writeMethod;
|
||||
|
||||
if (useAttributes)
|
||||
{
|
||||
writeMethod = xml.WriteAttributeString;
|
||||
}
|
||||
else // use elements
|
||||
{
|
||||
writeMethod = xml.WriteElementString;
|
||||
}
|
||||
|
||||
xml.WriteStartDocument();
|
||||
xml.WriteStartElement("categories");
|
||||
|
||||
foreach (Category c in categories)
|
||||
{
|
||||
xml.WriteStartElement("category");
|
||||
writeMethod("id", c.CategoryId.ToString());
|
||||
writeMethod("name", c.CategoryName);
|
||||
writeMethod("desc", c.Description);
|
||||
writeMethod("product_count", c.Products.Count.ToString());
|
||||
xml.WriteStartElement("products");
|
||||
|
||||
foreach (Product p in c.Products)
|
||||
{
|
||||
xml.WriteStartElement("product");
|
||||
|
||||
writeMethod("id", p.ProductId.ToString());
|
||||
writeMethod("name", p.ProductName);
|
||||
writeMethod("cost", p.Cost is null ? "0" : p.Cost.Value.ToString());
|
||||
writeMethod("stock", p.Stock.ToString());
|
||||
writeMethod("discontinued", p.Discontinued.ToString());
|
||||
|
||||
xml.WriteEndElement(); // </product>
|
||||
}
|
||||
xml.WriteEndElement(); // </products>
|
||||
xml.WriteEndElement(); // </category>
|
||||
}
|
||||
xml.WriteEndElement(); // </categories>
|
||||
}
|
||||
}
|
||||
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
arg0: xmlFile,
|
||||
arg1: new FileInfo(xmlFile).Length);
|
||||
}
|
||||
|
||||
static void GenerateCsvFile(IQueryable<Category> categories)
|
||||
{
|
||||
string csvFile = "categories-and-products.csv";
|
||||
|
||||
using (FileStream csvStream = File.Create(Combine(CurrentDirectory, csvFile)))
|
||||
{
|
||||
using (StreamWriter csv = new(csvStream))
|
||||
{
|
||||
|
||||
csv.WriteLine("CategoryId,CategoryName,Description,ProductId,ProductName,Cost,Stock,Discontinued");
|
||||
|
||||
foreach (Category c in categories)
|
||||
{
|
||||
foreach (Product p in c.Products)
|
||||
{
|
||||
csv.Write("{0},\"{1}\",\"{2}\",",
|
||||
arg0: c.CategoryId,
|
||||
arg1: c.CategoryName,
|
||||
arg2: c.Description);
|
||||
|
||||
csv.Write("{0},\"{1}\",{2},",
|
||||
arg0: p.ProductId,
|
||||
arg1: p.ProductName,
|
||||
arg2: p.Cost is null ? 0 : p.Cost.Value);
|
||||
|
||||
csv.WriteLine("{0},{1}",
|
||||
arg0: p.Stock,
|
||||
arg1: p.Discontinued);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
arg0: csvFile,
|
||||
arg1: new FileInfo(csvFile).Length);
|
||||
}
|
||||
|
||||
static void GenerateJsonFile(IQueryable<Category> categories)
|
||||
{
|
||||
string jsonFile = "categories-and-products.json";
|
||||
|
||||
using (FileStream jsonStream = File.Create(Combine(CurrentDirectory, jsonFile)))
|
||||
{
|
||||
using (Utf8JsonWriter json = new(jsonStream,
|
||||
new JsonWriterOptions { Indented = true }))
|
||||
{
|
||||
json.WriteStartObject();
|
||||
json.WriteStartArray("categories");
|
||||
|
||||
foreach (Category c in categories)
|
||||
{
|
||||
json.WriteStartObject();
|
||||
|
||||
json.WriteNumber("id", c.CategoryId);
|
||||
json.WriteString("name", c.CategoryName);
|
||||
json.WriteString("desc", c.Description);
|
||||
json.WriteNumber("product_count", c.Products.Count);
|
||||
|
||||
json.WriteStartArray("products");
|
||||
|
||||
foreach (Product p in c.Products)
|
||||
{
|
||||
json.WriteStartObject();
|
||||
|
||||
json.WriteNumber("id", p.ProductId);
|
||||
json.WriteString("name", p.ProductName);
|
||||
json.WriteNumber("cost", p.Cost is null ? 0 : p.Cost.Value);
|
||||
json.WriteNumber("stock", p.Stock is null ? 0 : p.Stock.Value);
|
||||
json.WriteBoolean("discontinued", p.Discontinued);
|
||||
|
||||
json.WriteEndObject(); // product
|
||||
}
|
||||
json.WriteEndArray(); // products
|
||||
json.WriteEndObject(); // category
|
||||
}
|
||||
json.WriteEndArray(); // categories
|
||||
json.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
||||
WriteLine("{0} contains {1:N0} bytes.",
|
||||
arg0: jsonFile,
|
||||
arg1: new FileInfo(jsonFile).Length);
|
||||
}
|
||||
}
|
||||
|
||||
23
vscode/Chapter10/Ch10Ex02DataSerialization/Program.cs
Normal file
23
vscode/Chapter10/Ch10Ex02DataSerialization/Program.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using Microsoft.EntityFrameworkCore; // Include extension method
|
||||
using Packt.Shared; // Northwind, Category, Product
|
||||
|
||||
WriteLine("Creating four files containing serialized categories and products.");
|
||||
|
||||
using (Northwind db = new())
|
||||
{
|
||||
// a query to get all categories and their related products
|
||||
IQueryable<Category>? categories = db.Categories?.Include(c => c.Products);
|
||||
|
||||
if (categories is null)
|
||||
{
|
||||
WriteLine("No categories found.");
|
||||
return;
|
||||
}
|
||||
|
||||
GenerateXmlFile(categories);
|
||||
GenerateXmlFile(categories, useAttributes: false);
|
||||
GenerateCsvFile(categories);
|
||||
GenerateJsonFile(categories);
|
||||
|
||||
WriteLine($"Current directory: {Environment.CurrentDirectory}");
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue