Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<None Remove="vegtable-sales.csv" />
</ItemGroup>
<ItemGroup>
<Content Include="vegetable-sales.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@ public static void Main(string[] args)
var dt = CreateMainDataTable();

PopulateDataTable(dt);
AddPrimaryKey(dt);
PrintConstraints(dt);
PrintData(dt);

DataTable dtClone = dt.Clone();
PrintColumns(dtClone);
PrintColumns(dtClone);

DataTable dtCopy = dt.Copy();
PrintData(dtCopy);

AddNewRow(dt);
FilterDataTable(dt);

PrintTable(dt);

SalesDataProcessor.ProcessSales();
}

Expand All @@ -32,45 +36,41 @@ public static DataTable CreateMainDataTable()
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("Price", typeof(double));

// add primary key
var pkCol = new DataColumn("Key", typeof(int));
dt.Columns.Add(pkCol);

var pkCols = new DataColumn[1];
pkCols[0] = pkCol;

dt.PrimaryKey = pkCols;

return dt;
}

public static void PopulateDataTable(DataTable dt)
{
// add row
// 1) declare and instantiate row
DataRow row;
row = dt.NewRow();
DataRow row = dt.NewRow();

// 2) set column values
row["Ticker"] = "MSFT";
row["Date"] = new DateTime(2023, 3, 3);
row["Price"] = 255.29;
row["Key"] = 0;
row["Price"] = 255.29;

// by Ordinal/index
row[0] = "MSFT";
row[1] = new DateTime(2023, 3, 3);
row[2] = 255.29;
row[3] = 0;

// 3) add populated row to table
dt.Rows.Add(row);
}

public static void AddPrimaryKey(DataTable dt)
{
var pkCol = new DataColumn("Key", typeof(int));
dt.Columns.Add(pkCol);

dt.Rows[0]["Key"] = 0;

dt.PrimaryKey = [pkCol];
}

public static void AddNewRow(DataTable dt)
{
DataRow row;
row = dt.NewRow();
DataRow row = dt.NewRow();

row["Ticker"] = "AMZN";
row["Date"] = new DateTime(2023, 3, 6);
Expand All @@ -80,6 +80,11 @@ public static void AddNewRow(DataTable dt)
dt.Rows.Add(row);
}

public static void AddNewRowFromValues(DataTable dt)
{
dt.Rows.Add("AMZN", new DateTime(2023, 3, 6), 93.75, 1);
}

public static void PrintConstraints(DataTable dt)
{
foreach (Constraint constraint in dt.Constraints)
Expand Down Expand Up @@ -124,5 +129,21 @@ public static void PrintData(DataTable dt)
}
}
}

public static void PrintTable(DataTable dt)
{
var header = dt.Columns.Cast<DataColumn>().Select(col => col.ColumnName);
Console.WriteLine(string.Join(" | ", header));

foreach (DataRow row in dt.Rows)
Console.WriteLine(string.Join(" | ", row.ItemArray));
}

public static IEnumerable<string?> GetTickersBelow(DataTable dt, double price)
{
return dt.AsEnumerable()
.Where(row => row.Field<double>("Price") < price)
.Select(row => row.Field<string>("Ticker"));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ public static void ProcessSales()

public static DataTable CsvToDataTable(string filePath)
{
DataTable dtRes = new DataTable();
var dtRes = new DataTable();
using (var parser = new TextFieldParser(filePath))
{
parser.TextFieldType = FieldType.Delimited;
parser.TrimWhiteSpace = true;
parser.SetDelimiters(",");

var columns = parser.ReadFields();
var columns = parser.ReadFields() ?? [];

foreach (var col in columns)
dtRes.Columns.Add(col);

while (!parser.EndOfData)
{
var row = parser.ReadFields();
var row = parser.ReadFields() ?? [];
dtRes.LoadDataRow(row, true);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Pepper,2,2,4
Cucumber,4,1,4
Lettuce,6,0.5,3
Asparagus,2,2.5,5
Carrot,1,3,1
Carrot,1,3,3
Broccoli,2,0.75,1.5
Pepper,4,2,8
Cucumber,7,1,7
Expand Down
102 changes: 91 additions & 11 deletions csharp-intermediate-topics/DataTableOverview/Tests/ProgramTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,23 @@

namespace Tests
{
[Collection("Console output")]
public class ProgramTests
{
private static DataTable CreateKeyedTable()
{
var dt = Program.CreateMainDataTable();
Program.PopulateDataTable(dt);
Program.AddPrimaryKey(dt);

return dt;
}

[Fact]
public static void WhenCreateMainDataTable_ThenColumnsPopulateCorrectly()
{
var dt = Program.CreateMainDataTable();
var expectedColumns = new string[] { "Ticker", "Date", "Price", "Key" };
var expectedColumns = new string[] { "Ticker", "Date", "Price" };

var actualColumns = dt.Columns.Cast<DataColumn>()
.Select(x => x.ColumnName)
Expand All @@ -21,13 +31,25 @@ public static void WhenCreateMainDataTable_ThenColumnsPopulateCorrectly()
}

[Fact]
public static void WhenCreateMaindataTable_ThenPrimaryKeyEqualsKey()
public static void WhenAddPrimaryKey_ThenPrimaryKeyEqualsKey()
{
var dt = Program.CreateMainDataTable();
var dt = CreateKeyedTable();

var pkActual = dt.PrimaryKey;

Assert.Equal("Key", pkActual[0].Caption);
Assert.Equal(0, dt.Rows[0]["Key"]);
}

[Fact]
public static void WhenPrimaryKeySetOnColumnWithEmptyValues_ThenDataExceptionThrown()
{
var dt = Program.CreateMainDataTable();
Program.PopulateDataTable(dt);
var pkCol = new DataColumn("Key", typeof(int));
dt.Columns.Add(pkCol);

Assert.Throws<DataException>(() => dt.PrimaryKey = [pkCol]);
}

[Fact]
Expand All @@ -43,17 +65,36 @@ public static void WhenPopulateDataTable_ThenDataTableContainsMsftRecord()
[Fact]
public static void WhenAddNewRow_ThenDataTableContainsAmznRecord()
{
var dt = Program.CreateMainDataTable();
var dt = CreateKeyedTable();

Program.AddNewRow(dt);

Assert.Contains("AMZN", Convert.ToString(dt.Rows[0][0]));
Assert.Contains("AMZN", Convert.ToString(dt.Rows[1][0]));
}

[Fact]
public static void WhenAddNewRowFromValues_ThenDataTableContainsAmznRecord()
{
var dt = CreateKeyedTable();

Program.AddNewRowFromValues(dt);

Assert.Equal("AMZN", dt.Rows[1]["Ticker"]);
Assert.Equal(1, dt.Rows[1]["Key"]);
}

[Fact]
public static void WhenRowAddedWithDuplicateKey_ThenConstraintExceptionThrown()
{
var dt = CreateKeyedTable();

Assert.Throws<ConstraintException>(() => dt.Rows.Add("AMZN", new DateTime(2023, 3, 6), 93.75, 0));
}

[Fact]
public static void WhenPrintConstraints_ThenReturnsConstraintOneUniqueConstraint()
{
var dt = Program.CreateMainDataTable();
var dt = CreateKeyedTable();

var stringWriter = new StringWriter();
Console.SetOut(stringWriter);
Expand All @@ -65,10 +106,21 @@ public static void WhenPrintConstraints_ThenReturnsConstraintOneUniqueConstraint
Assert.Contains("System.Data.UniqueConstraint", output);
}

[Fact]
public static void WhenCloneCalled_ThenAllColumnsAndNoRowsCopied()
{
var dt = CreateKeyedTable();

var dtClone = dt.Clone();

Assert.Equal(4, dtClone.Columns.Count);
Assert.Empty(dtClone.Rows);
}

[Fact]
public static void WhenFilterDataTable_ThenPrintsAmznDataRow()
{
var dt = Program.CreateMainDataTable();
var dt = CreateKeyedTable();
Program.AddNewRow(dt);

var stringWriter = new StringWriter();
Expand All @@ -78,13 +130,13 @@ public static void WhenFilterDataTable_ThenPrintsAmznDataRow()
var output = stringWriter.ToString();

Assert.Contains("AMZN", output);
Assert.DoesNotContain("MSFT", output);
}

[Fact]
public static void WhenPrintData_ThenPrintsExpectedData()
{
var dt = Program.CreateMainDataTable();
Program.PopulateDataTable(dt);
var dt = CreateKeyedTable();

var stringWriter = new StringWriter();
Console.SetOut(stringWriter);
Expand All @@ -95,7 +147,35 @@ public static void WhenPrintData_ThenPrintsExpectedData()
Assert.Contains("MSFT", output);
Assert.Contains(Convert.ToString(new DateTime(2023, 3, 3)), output);
Assert.Contains("255.29", output);
Assert.Contains("0", output);
Assert.Contains("Key: 0", output);
}

[Fact]
public static void WhenPrintTable_ThenPrintsHeaderAndOneLinePerRow()
{
var dt = CreateKeyedTable();
Program.AddNewRow(dt);

var stringWriter = new StringWriter();
Console.SetOut(stringWriter);

Program.PrintTable(dt);
var lines = stringWriter.ToString().Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries);

Assert.Equal("Ticker | Date | Price | Key", lines[0]);
Assert.Equal(3, lines.Length);
Assert.StartsWith("AMZN | ", lines[2]);
}

[Fact]
public static void WhenGetTickersBelow_ThenReturnsOnlyCheaperTickers()
{
var dt = CreateKeyedTable();
Program.AddNewRow(dt);

var tickers = Program.GetTickersBelow(dt, 100);

Assert.Equal(new[] { "AMZN" }, tickers);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using DataTableOverview;
using Microsoft.VisualStudio.TestPlatform.TestHost;
using Xunit;
using System;

namespace Tests
{
[Collection("Console output")]
public class SalesDataProcessorTests
{
[Fact]
Expand Down Expand Up @@ -32,6 +32,15 @@ public void WhenProcessSales_ThenPrintsSelectedRows()

Assert.Contains("Carrot", output);
}

[Fact]
public void WhenNumericFilterRunsOnCsvColumn_ThenEvaluateExceptionThrown()
{
var filePath = AppDomain.CurrentDomain.BaseDirectory + "vegetable-sales.csv";
var veggieSales = SalesDataProcessor.CsvToDataTable(filePath);

Assert.Equal(typeof(string), veggieSales.Columns["Price"]!.DataType);
Assert.Throws<System.Data.EvaluateException>(() => veggieSales.Select("Price > 1"));
}
}
}

10 changes: 5 additions & 5 deletions csharp-intermediate-topics/DataTableOverview/Tests/Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PackageReference Include="coverlet.collector" Version="10.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Loading