-
Notifications
You must be signed in to change notification settings - Fork 15
Code changes history
- Moved all executables (unit tests, samples) to .NET 6. Upgraded all Db provider packages to latest versions
- "Modernized solution" a bit - moved nuget package generation to 'make package on build', in Release mode. Switched symbol packages to newer format 'snupkg'
- Big internal refactoring. Encountered a real-world case, a database for which the db-first code generator could not produce the entities code that would not fail at startup (model build errors). The specific trouble was a widespread use of composite primary and foreign keys. After a few attempts of small fixes, had to take it seriously - make a full investigation and analysis, understand the cause, and do a large refactoring of model-build methods, specifically Keys building process. Finally its done, looks like all working, including this puzzling database that started it all.
- Fixed a few other minor things, including investigating and fixing/not-fixing a few issues
- DbSettings.UpgradeSettings.IgnoreDbObjects - list of names of objects to ignore when upgrading db schema. Useful when you have some artifacts created manually or thru migrations; add full object name to this list to prevent auto schema upgrade process from deleting it
- Alternatively you can handle app.DataSourceEvents.DbUpgrading event to intercept db upgrade process. This event had been extended, it is fired several times at different stages of upgrade process
- Custom LINQ functions implemented as SQL expressions .
- DB-computed members (generated columns), based on SQL expressions)
You can now define a static function (extension method) that you can use in LINQ queries against the database, and it will be implemented as a custom SQL expression inside the final SELECT query. You define SQL expressions, one per each server type, using SqlExpression attribute. Here is a DbAddYears function: https://github.com/rivantsov/vita/blob/476983f2b5927da8207c4d5fd06e17ebce72091b/src/6.UnitTests/Vita.Testing.BasicTests/MiscTests_Model.cs#L138
and here how you use it: https://github.com/rivantsov/vita/blob/476983f2b5927da8207c4d5fd06e17ebce72091b/src/6.UnitTests/Vita.Testing.BasicTests/MiscTests.cs#L363
DB-computed members are similar - an entity member that has an underlying SQL Expression. There are 3 types of DB-computed members:
- Expression only - there is no DB column, entity member value is computed from a give SQL snippet in SELECTs
- Column (aka Virtual Column) - column in db table without actual storage, it is calculated by database on the fly
- Stored column - the column is computed on create/update and the value is stored in the table row.
Not all servers support both virtual and stored columns. Oracle does not support Stored columns; Postgres does not support Virtual. Additional trouble is with DB upgrade. Servers parse and reformat the expression when creating generated columns, so detecting diff db/entities is a challenge. For MS SQL, MySql, Postgres - start with custom expr, start the app, look at reformatted expr, and replace the value in the attribute with the value now in the database. For your convenience, VITA prints out both expressions to Debug output when DB upgrade detects the difference.
For Oracle, things are much worse. Expression is available but it is stored in LONG column - Oracle deprecated LONG data type long ago, and currently there is no way to read the value with .NET Oracle provider. So for Oracle, it's all or nothing - there's a static flag in OracleDbDriver that controls this.
Here is an example of DB computed columns:
The biggest addition is a first draft of GraphQL integration - and a sample GraphQL server with ASP.NET Core and NGraphQL. The majority of the GraphQL service is outside VITA code. But there is one advanced feature added in VITA to support GraphQL: the SmartLoad facility. It is a solution for the (N+1) problem in GraphQL, but I see it absolutely useful in general, outside of GraphQL context. SmartLoad is about automatically batch-loading the related entities, just like with Include's, but without explicitly specifying the Include expressions in the original query. I will write a separate doc about this feature and how it works.
Other fixes:
- Fix for problem of loading list properties with includes, when empty lists results were not registered as empty, and caused repeated db calls to load them again.
- SelectMany LINQ method worked incorrectly, returning nulls instead of objects; now fixed.
- For many-to-many list properties, the link entity is now available through EntityHelper.GetLinkEntities help method. This makes it possible to have extra properties on link entities.
- For Web API: Jwt token info is now available in OperationContext under keys defined in VitaJwtTokenHandler class.
- For MS SQL Server the provider is changed to Microsoft.Data.SqlClient (from System.Data.SqlClient). See https://www.sqlservercentral.com/blogs/moving-to-a-new-sqlclient for more info. Important: if you reference the SqlClient classes directly in your code, you need to switch to this package as well.
- Restored NoColumn attribute functionality - the attribute marks entity property that has no underlying column, it is in-memory only value in entity.
- Internal changes to projects - removed AssemblyInfo.cs files, switched to using only info in .csproj files; latest recommended arrangement.
- Fix - Logging to file in Web app
- Fix: Aggregate over int column throwing exception
- Fix for issue 146 - exception thrown on entity ref assignment
- Hooked AppEvents.Connected event
- Fixed use of default size in Size attr (issue #132)
- Added ILogFileWriter interface (issue #121)
- Fixed CreatePrimaryKey method for composite-over-composite keys
- Fixed LINQ list.Contains(long values) expressions in MS SQL Server for long (BIGINT) columns/lists.
-
Solution moved to Visual Studio 2019 and .NET Core 3.1 SDK. Read the SourceCodeOverview.txt for instructions of additonal setup you need to run the tests; you need to create VitaBooksLogs empty database and adjust connection string in WebTests project.
-
Vita.Entities.Emit project is gone - this separate project/assembly is removed, classes moved to the main Vita assembly which directly references the Proxemity package. No more need to set the MyApp.EntityClassProvider property at startup. I realized that this arrangement (separate assembly to handle dependency on Emit) - brings more trouble than it's worth.
-
Logging infrastructure rebuild. Logging to database using Vita.Modules.Logging module and app. You can now direct logs to a dedicated database, see WebTests project for an example of setup. Logging to file - still available, just set the EntityApp.LogPath property. In the plans - logging to other destinations. The sources contain a draft of client for Azure LogAnalytics.
-
Vita.Web package (re-introduced) - integration with ASP.NET-Core 3.1 Web stack. Provides VitaWebMiddleware - a middleware/interceptor for Http pipeline, see WebTests test project for example of setup. Other classes: VitaJwtTokenHandler - provides handling of authentication over HTTP using Jwt tokens; BaseApiController - base case for your API controllers, integrated with the middleware.
Major functionality provided by the middleware:
- Intercepts the HTTP request, sets up an OperationContext and WebContext instances used by API controllers to access the data in the context of the currently logged-in user.
- Handles the ClientFaultException (soft error) from the controller/business logic and translates it into BadRequest returned to the client, with list of faults in the body.
- Logs the request information to the log. Look at WebCallLog table in the VitaBooksLogs database after running the WebTests. For each request you can see complete information, including SQL log - all SQLs that had been fired when processing the request.
Note: Although Vita.Web package and its classes can be used directly in your Web application, I recommend to look at them more like a sample and use its source code as a starting point for your own custom solution; most likely real-world cases would need far more customized solution. But it works AS-IS in most standard scenarios.
-
New Web API packages/projects - API implementations and tests based on Vita.Web. Login module now exposes all its functionality over REST-ful API, implemented in Vita.Modules.Login.Api package. BookStore sample app has API implementation project that is tested (along with Login API) in the WebTests project.
-
WebTests test project. The app starts a REST-ful service for the sample BookStore app, and hits the API endpoints. Shows how to handle login and authenticated users. Uses new separate Arrest package for REST client, available here: https://github.com/rivantsov/arrest
-
Vita.Modules.Legacy package - several entity modules brought back from old 1.9 solution (pre- .NET-core), for backward support of existing apps. The LEGACY token indicates that although the code is fully supported, no future development or enhancement is planned.