|
| 1 | +# Entity Framework Core - MergeOptionFeature Test Guide |
| 2 | + |
| 3 | +This guide provides a comprehensive overview of all tests in the `Microsoft.EntityFrameworkCore.MergeOptionFeature` namespace. These tests are designed to validate the refresh functionality (merge options) across various Entity Framework Core features when entities are refreshed from the database after external changes. |
| 4 | + |
| 5 | +## Background |
| 6 | + |
| 7 | +The MergeOptionFeature tests simulate scenarios where database data changes externally (outside of the current EF Core context), and then test how EF Core handles refreshing entities to reflect these external changes. This is crucial for applications that need to stay synchronized with database changes made by other processes, users, or systems. |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +## Test 1: RefreshFromDb_Northwind_SqlServer_Test |
| 12 | + |
| 13 | +### 1.1 EF Core Features Tested |
| 14 | +This test focuses on **basic entity refresh functionality** using the standard Northwind database model. It tests core scenarios like: |
| 15 | +- Entity states (Unchanged, Modified, Added, Deleted) |
| 16 | +- Query terminating operators (ToList, FirstOrDefault, etc.) |
| 17 | +- Include operations for loading related data |
| 18 | +- Lazy loading with proxies |
| 19 | +- Non-tracking queries |
| 20 | +- Streaming vs buffering query consumption |
| 21 | + |
| 22 | +### 1.2 Test Context and Model |
| 23 | +- **Context**: Uses `NorthwindQuerySqlServerFixture<NoopModelCustomizer>` |
| 24 | +- **Model**: Standard Northwind database (Customers, Orders, Products, etc.) |
| 25 | +- **Elements**: Real-world entities with established relationships |
| 26 | +- **Database**: SQL Server with pre-seeded Northwind data |
| 27 | + |
| 28 | +### 1.3 Global Test Purpose |
| 29 | +Validates that EF Core's basic refresh mechanisms work correctly across different entity states and query patterns. Ensures that external database changes are properly reflected when entities are refreshed, and that the change tracking system maintains consistency. |
| 30 | + |
| 31 | +### 1.4 Test Methods Overview |
| 32 | +- **Entity State Tests**: Verify refresh behavior for entities in different states (Added, Modified, Deleted, Unchanged) |
| 33 | +- **Query Pattern Tests**: Test refresh with different LINQ terminating operators and consumption patterns |
| 34 | +- **Include Tests**: Validate refresh behavior when related entities are loaded via Include operations |
| 35 | +- **Proxy Tests**: Test lazy loading proxy behavior during refresh operations |
| 36 | +- **Error Condition Tests**: Ensure proper exceptions are thrown for invalid refresh scenarios (e.g., non-tracking queries) |
| 37 | + |
| 38 | +--- |
| 39 | + |
| 40 | +## Test 2: RefreshFromDb_ComplexTypes_SqlServer_Test |
| 41 | + |
| 42 | +### 2.1 EF Core Features Tested |
| 43 | +This test focuses on **Complex Types** - value objects that are embedded within entities but don't have their own identity. Features tested: |
| 44 | +- Owned types (both collection and non-collection) |
| 45 | +- Complex properties of value and reference types |
| 46 | +- Refresh behavior for nested value objects |
| 47 | +- JSON serialization of complex data |
| 48 | + |
| 49 | +### 2.2 Test Context and Model |
| 50 | +- **Context**: Custom `ComplexTypesContext` with specially designed entities |
| 51 | +- **Model**: |
| 52 | + - `Product` with owned `ProductDetails` and owned collection `Reviews` |
| 53 | + - `Customer` with complex property `ContactInfo` and owned collection `Addresses` |
| 54 | +- **Elements**: Demonstrates embedding complex objects within main entities |
| 55 | +- **Database**: Custom tables with JSON columns and nested object storage |
| 56 | + |
| 57 | +### 2.3 Global Test Purpose |
| 58 | +Validates that EF Core correctly refreshes complex types and owned entities when the underlying database data changes. Ensures that nested objects maintain their structure and relationships during refresh operations. |
| 59 | + |
| 60 | +### 2.4 Test Methods Overview |
| 61 | +- **Collection Owned Types**: Tests refreshing when owned collections (like Reviews) change externally |
| 62 | +- **Non-Collection Owned Types**: Tests refreshing simple owned objects (like ProductDetails) |
| 63 | +- **Collection Complex Properties**: Tests refreshing complex collections (like Addresses) |
| 64 | +- **Non-Collection Complex Properties**: Tests refreshing simple complex objects (like ContactInfo) |
| 65 | + |
| 66 | +--- |
| 67 | + |
| 68 | +## Test 3: RefreshFromDb_ComputedColumns_SqlServer_Test |
| 69 | + |
| 70 | +### 3.1 EF Core Features Tested |
| 71 | +This test focuses on **Computed Columns** - database columns whose values are calculated by the database engine rather than stored directly. Features tested: |
| 72 | +- Properties mapped to computed columns |
| 73 | +- Mathematical computations (Price * Quantity) |
| 74 | +- String concatenation formulas |
| 75 | +- Date formatting expressions |
| 76 | +- Database-generated calculated values |
| 77 | + |
| 78 | +### 3.2 Test Context and Model |
| 79 | +- **Context**: Custom `ComputedColumnsContext` with computed column definitions |
| 80 | +- **Model**: |
| 81 | + - `Product` with `TotalValue` (Price * Quantity) and `Description` (Name + Price formatted) |
| 82 | + - `Order` with `FormattedOrderDate` (formatted date string) |
| 83 | +- **Elements**: SQL Server computed column expressions using T-SQL functions |
| 84 | +- **Database**: Tables with computed columns using SQL Server-specific syntax |
| 85 | + |
| 86 | +### 3.3 Global Test Purpose |
| 87 | +Ensures that computed columns are correctly refreshed when their underlying base columns change. Validates that database-calculated values are properly materialized into .NET properties during refresh operations. |
| 88 | + |
| 89 | +### 3.4 Test Methods Overview |
| 90 | +- **Basic Computed Columns**: Tests refreshing entities where computed values depend on other columns |
| 91 | +- **Query Integration**: Validates that computed columns work correctly in LINQ queries |
| 92 | +- **Database-Generated Updates**: Tests refresh when computed columns use database functions like date formatting |
| 93 | + |
| 94 | +--- |
| 95 | + |
| 96 | +## Test 4: RefreshFromDb_GlobalFilters_SqlServer_Test |
| 97 | + |
| 98 | +### 4.1 EF Core Features Tested |
| 99 | +This test focuses on **Global Query Filters** - automatically applied WHERE clauses that filter entities globally across all queries. Features tested: |
| 100 | +- Multi-tenancy filtering (filtering by TenantId) |
| 101 | +- Soft delete patterns (filtering out deleted records) |
| 102 | +- Dynamic filter contexts (changing filter values at runtime) |
| 103 | +- Filter bypass using `IgnoreQueryFilters()` |
| 104 | + |
| 105 | +### 4.2 Test Context and Model |
| 106 | +- **Context**: Custom `GlobalFiltersContext` with tenant-aware filtering |
| 107 | +- **Model**: |
| 108 | + - `Product` with multi-tenancy filter (`TenantId == CurrentTenantId`) |
| 109 | + - `Order` with both multi-tenancy and soft delete filters (`TenantId == CurrentTenantId && !IsDeleted`) |
| 110 | +- **Elements**: Context property `TenantId` that controls filtering behavior |
| 111 | +- **Database**: Tables with tenant and soft delete columns |
| 112 | + |
| 113 | +### 4.3 Global Test Purpose |
| 114 | +Validates that global query filters work correctly during refresh operations, ensuring entities remain properly filtered even when refreshed from the database. Tests that filter context changes affect entity visibility as expected. |
| 115 | + |
| 116 | +### 4.4 Test Methods Overview |
| 117 | +- **Basic Filter Tests**: Ensures filtered entities refresh correctly within their filter scope |
| 118 | +- **Filter Bypass Tests**: Tests `IgnoreQueryFilters()` to access normally filtered entities |
| 119 | +- **Dynamic Context Tests**: Validates changing filter context (tenant switching) affects entity visibility |
| 120 | +- **Soft Delete Tests**: Tests the common soft delete pattern with global filters |
| 121 | + |
| 122 | +--- |
| 123 | + |
| 124 | +## Test 5: RefreshFromDb_ManyToMany_SqlServer_Test |
| 125 | + |
| 126 | +### 5.1 EF Core Features Tested |
| 127 | +This test focuses on **Many-to-Many Relationships** without explicit join entities. Features tested: |
| 128 | +- Modern EF Core many-to-many configuration |
| 129 | +- Automatic join table management |
| 130 | +- Bidirectional relationship updates |
| 131 | +- Collection navigation refresh |
| 132 | +- Multiple relationship manipulation |
| 133 | + |
| 134 | +### 5.2 Test Context and Model |
| 135 | +- **Context**: Custom `ManyToManyContext` with modern many-to-many setup |
| 136 | +- **Model**: |
| 137 | + - `Student` ? `Course` (StudentCourse join table) |
| 138 | + - `Author` ? `Book` (AuthorBook join table) |
| 139 | +- **Elements**: Uses `HasMany().WithMany().UsingEntity()` configuration |
| 140 | +- **Database**: Automatic join tables managed by EF Core |
| 141 | + |
| 142 | +### 5.3 Global Test Purpose |
| 143 | +Ensures that many-to-many relationships are correctly refreshed when join table records change externally. Validates that both sides of the relationship reflect changes when navigation collections are refreshed. |
| 144 | + |
| 145 | +### 5.4 Test Methods Overview |
| 146 | +- **Add Relationships**: Tests adding new many-to-many connections externally and refreshing |
| 147 | +- **Remove Relationships**: Tests removing connections and refreshing to reflect removal |
| 148 | +- **Bidirectional Updates**: Ensures both sides of relationships update when refreshed |
| 149 | +- **Multiple Operations**: Tests handling multiple relationship changes simultaneously |
| 150 | + |
| 151 | +--- |
| 152 | + |
| 153 | +## Test 6: RefreshFromDb_PrimitiveCollections_SqlServer_Test |
| 154 | + |
| 155 | +### 6.1 EF Core Features Tested |
| 156 | +This test focuses on **Primitive Collections** - collections of primitive types (string, int, Guid) stored as JSON in database columns. Features tested: |
| 157 | +- JSON column mapping for collections |
| 158 | +- Primitive collection configuration |
| 159 | +- Collection serialization/deserialization |
| 160 | +- Empty collection handling |
| 161 | +- Various primitive types (strings, integers, GUIDs) |
| 162 | + |
| 163 | +### 6.2 Test Context and Model |
| 164 | +- **Context**: Custom `PrimitiveCollectionsContext` with JSON column storage |
| 165 | +- **Model**: |
| 166 | + - `Product` with `List<string> Tags` stored as JSON |
| 167 | + - `Blog` with `List<int> Ratings` stored as JSON |
| 168 | + - `User` with `List<Guid> RelatedIds` stored as JSON |
| 169 | +- **Elements**: Uses `PrimitiveCollection()` configuration method |
| 170 | +- **Database**: JSON columns in SQL Server for collection storage |
| 171 | + |
| 172 | +### 6.3 Global Test Purpose |
| 173 | +Validates that primitive collections stored as JSON are correctly refreshed when the underlying JSON data changes. Ensures proper serialization/deserialization during refresh operations. |
| 174 | + |
| 175 | +### 6.4 Test Methods Overview |
| 176 | +- **String Collections**: Tests refreshing collections of strings (tags, categories) |
| 177 | +- **Number Collections**: Tests refreshing collections of integers (ratings, scores) |
| 178 | +- **GUID Collections**: Tests refreshing collections of GUIDs (identifiers) |
| 179 | +- **Empty Collections**: Tests edge cases with empty collections and null handling |
| 180 | + |
| 181 | +--- |
| 182 | + |
| 183 | +## Test 7: RefreshFromDb_ShadowProperties_SqlServer_Test |
| 184 | + |
| 185 | +### 7.1 EF Core Features Tested |
| 186 | +This test focuses on **Shadow Properties** - properties that exist in the EF model and database but not as .NET class properties. Features tested: |
| 187 | +- Shadow property configuration |
| 188 | +- Accessing shadow properties via `Entry().Property()` |
| 189 | +- Shadow foreign keys for relationships |
| 190 | +- Querying using `EF.Property<T>()` method |
| 191 | +- Mixed shadow and regular properties |
| 192 | + |
| 193 | +### 7.2 Test Context and Model |
| 194 | +- **Context**: Custom `ShadowPropertiesContext` with shadow property definitions |
| 195 | +- **Model**: |
| 196 | + - `Product` with shadow properties `CreatedBy`, `CreatedAt`, `LastModified` |
| 197 | + - `Order` with shadow foreign key `CustomerId` |
| 198 | +- **Elements**: Properties defined in model but not in .NET classes |
| 199 | +- **Database**: Regular database columns mapped to shadow properties |
| 200 | + |
| 201 | +### 7.3 Global Test Purpose |
| 202 | +Ensures that shadow properties are correctly refreshed even though they don't exist as .NET properties. Validates that the entity framework properly manages these "invisible" properties during refresh operations. |
| 203 | + |
| 204 | +### 7.4 Test Methods Overview |
| 205 | +- **Basic Shadow Properties**: Tests refreshing shadow properties like audit fields |
| 206 | +- **Mixed Property Types**: Tests refreshing entities with both regular and shadow properties |
| 207 | +- **Shadow Foreign Keys**: Tests refreshing shadow properties used as foreign keys |
| 208 | +- **Query Integration**: Tests using shadow properties in LINQ queries with `EF.Property<T>()` |
| 209 | + |
| 210 | +--- |
| 211 | + |
| 212 | +## Test 8: RefreshFromDb_TableSharing_SqlServer_Test |
| 213 | + |
| 214 | +### 8.1 EF Core Features Tested |
| 215 | +This test focuses on **Table Sharing** - multiple entity types mapping to the same database table. Features tested: |
| 216 | +- Multiple entities sharing table storage |
| 217 | +- Shared non-key columns between entities |
| 218 | +- Table Per Type (TPT) inheritance patterns |
| 219 | +- One-to-one relationships with shared storage |
| 220 | +- Independent entity updates on shared tables |
| 221 | + |
| 222 | +### 8.2 Test Context and Model |
| 223 | +- **Context**: Custom `TableSharingContext` with multiple entities per table |
| 224 | +- **Model**: |
| 225 | + - `Person` and `Employee` sharing "People" table |
| 226 | + - `Blog` and `BlogMetadata` sharing "Blogs" table |
| 227 | + - `Vehicle` and `Car` (inheritance) sharing "Vehicles" table |
| 228 | +- **Elements**: Uses `ToTable()` to map multiple entities to same table |
| 229 | +- **Database**: Single tables storing data for multiple entity types |
| 230 | + |
| 231 | +### 8.3 Global Test Purpose |
| 232 | +Validates that entities sharing table storage are correctly refreshed when shared columns change. Ensures that updates to shared data are visible to all entity types that map to the same table. |
| 233 | + |
| 234 | +### 8.4 Test Methods Overview |
| 235 | +- **Shared Column Updates**: Tests when shared columns (like Name) are updated externally |
| 236 | +- **Independent Entity Updates**: Tests entity-specific columns on shared tables |
| 237 | +- **Inheritance Scenarios**: Tests table sharing with inheritance hierarchies |
| 238 | +- **Relationship Sharing**: Tests entities in relationships that share storage |
| 239 | + |
| 240 | +--- |
| 241 | + |
| 242 | +## Test 9: RefreshFromDb_ValueConverters_SqlServer_Test |
| 243 | + |
| 244 | +### 9.1 EF Core Features Tested |
| 245 | +This test focuses on **Value Converters** - custom conversion logic between .NET types and database storage types. Features tested: |
| 246 | +- Enum to string conversion |
| 247 | +- Collection to JSON conversion |
| 248 | +- DateTime to string formatting |
| 249 | +- GUID to string representation |
| 250 | +- Custom value object conversion |
| 251 | +- Built-in and custom converter patterns |
| 252 | + |
| 253 | +### 9.2 Test Context and Model |
| 254 | +- **Context**: Custom `ValueConvertersContext` with various converter types |
| 255 | +- **Model**: |
| 256 | + - `Product` with enum-to-string and collection-to-JSON converters |
| 257 | + - `User` with DateTime-to-string and GUID-to-string converters |
| 258 | + - `Order` with custom `Money` value object converter |
| 259 | +- **Elements**: Uses `HasConversion()` method with custom conversion logic |
| 260 | +- **Database**: Storage types different from .NET types (strings, JSON, decimals) |
| 261 | + |
| 262 | +### 9.3 Global Test Purpose |
| 263 | +Ensures that value converters work correctly during refresh operations, properly converting between database storage formats and .NET types. Validates that external changes in the database format are correctly converted back to .NET objects. |
| 264 | + |
| 265 | +### 9.4 Test Methods Overview |
| 266 | +- **Enum Converters**: Tests enum values stored as strings in database |
| 267 | +- **JSON Converters**: Tests complex objects serialized as JSON |
| 268 | +- **DateTime Converters**: Tests custom date formatting patterns |
| 269 | +- **GUID Converters**: Tests GUID-to-string conversion patterns |
| 270 | +- **Value Object Converters**: Tests custom value objects with conversion logic |
| 271 | + |
| 272 | +--- |
| 273 | + |
| 274 | +## Key Concepts for Understanding These Tests |
| 275 | + |
| 276 | +### Entity Refresh (ReloadAsync) |
| 277 | +The core operation being tested - refreshing an entity from the database to pick up external changes. |
| 278 | + |
| 279 | +### External Changes Simulation |
| 280 | +Tests use `ExecuteSqlRawAsync()` to simulate changes made outside the current EF context, representing real-world scenarios like other applications, users, or processes modifying data. |
| 281 | + |
| 282 | +### Change Tracking Integration |
| 283 | +All tests validate that refresh operations work correctly with EF's change tracking system, maintaining consistency between tracked entities and database state. |
| 284 | + |
| 285 | +### Provider-Specific Testing |
| 286 | +These are SQL Server-specific tests, ensuring that refresh functionality works with SQL Server's specific features and data types. |
| 287 | + |
| 288 | +### Comprehensive Coverage |
| 289 | +Together, these tests cover the full spectrum of EF Core features to ensure refresh functionality works across all scenarios that applications might encounter. |
| 290 | + |
| 291 | +--- |
| 292 | + |
| 293 | +## Running the Tests |
| 294 | + |
| 295 | +To run these tests: |
| 296 | +1. Ensure SQL Server is available (LocalDB is sufficient) |
| 297 | +2. Run `restore.cmd` to restore dependencies |
| 298 | +3. Run `. .\activate.ps1` to setup the development environment |
| 299 | +4. Execute tests using `dotnet test` or Visual Studio Test Explorer |
| 300 | +5. Tests will create temporary databases and clean up automatically |
| 301 | + |
| 302 | +Each test is designed to be independent and can be run individually or as a suite to validate the entire refresh functionality across all EF Core features. |
0 commit comments