Unreleased

Fixed

  • [ORM] LINQ queries including .Properties threw an IndexOutOfRangeException; now you get a tailored error explaining not to do that.

Changed

  • [ORM] PersistenceService.ConnectAsync now returns ConnectResult directly and throws on failure, similarly to ReadAsync/WriteAsync. (Apps don't generally use this API directly.)

Added

  • [MDL] Entity, Attribute and RelationshipSide nodes now support a SummaryComment property. When set, generated C# code emits /// <summary> xmldoc comments on entity classes, attribute properties and relationship navigation properties.
  • [WPF] Routine-error overlays like "Server Unreachable" can be replaced by others like "Version Mismatch" if necessary.

357.6.1

Fixed

  • [WPF] ZomboBox/MultiZomboBox dropdown didn't close when clicking on non-focusable areas (e.g. the results list on a search screen).
  • [WPF] Some criterion field types weren't RaisingPropertyChanged("Value") when their Value changed. Relatedly, Criteria screens watched all field properties for changes, executing needless searches and causing flicker.

357.6.0

Changed

  • [MDL] The extension now supports (and requires) .NET 10. Previously, it required .NET 8 installed, even if you were using .NET 10 for your application's runtime.
  • [WPF] RelationshipOptionsField now uses a MultiZomboBox for inline criteria entry.

Fixed

  • [ORM] OwnedSet implementation of INotifyCollectionChanged was incorrect for AddRange() and RemoveRange().

357.5.1

Added

  • [WEB] <BoundTask Once> - if set, changes to the Binding parameter after a returned task has been awaited won't invoke the new value to generate a new task.

Fixed

  • [WEB] <SidebarShell> was duplicating the "App (Env)" titling logic that's now in the core framework.
  • [WPF] EnumInlineCollectionField starts in selector mode (editable) when selecting reference data, like LookupInlineReferenceField does.
  • [ORM] Fixed false positives in concurrent mutation detection when a serialising SynchronizationContext is provided (as Blazor does).

357.5.0

Added

  • [WPF] MultiZomboBox, a multiple-selection equivalent of ZomboBox. It has the same featureset, but with IList SelectedItems instead of object SelectedItem. The selected items are represented as chips which can be clicked to remove them individually; backspace will also remove the last item.
  • [WPF] EnumInlineCollectionField, an inline counterpart of EnumSectionedCollectionField. It uses a MultiZomboBox to select multiple items into an IEntitySet<T> from an IEntityQuery<T>. EICF is the new default for collections of reference data (hence the name), but it can be used as a custom field for other types; the design is appropriate for selecting "a few things" from "maybe dozens but not thousands" of choices.
  • [WEB] Exposed configuration for The.Composition.Options.ConcurrentMutation in The.Web.Composition.Options.

357.4.0

Added

  • [ORM] WriteOutcome.Persistent can now be used on servers . If this is set as part of a WritePolicy and an ICacheStore is provided, the persistent data will be loaded once and shared between scoped framework instances (as other cached data already was).

Changed

  • [ORM] TransientCache has been renamed to SharedCache and now contains ICacheStore (formerly IPersistentCache) directly, correcting a design flaw. Breaking in theory, but no apps directly use these types so we're calling it a .1.

Fixed

  • [MDL] Newly-added sections didn't show up in the Section dropdown for existing entity properties.
  • [ORM] EntityCache no longer uses a scheduled timer for statistics logging - it was causing memory leaks.
  • [WPF] Reminders sidebar instances shared the same preferences namespace, so their expansion state didn't save properly when you put them in a Multibar.

357.3.1

Added

  • [WPF] ContentController dynamic section visibility - RaisePropertyChanged(IsVisible) to hide or show.

Fixed

  • [WPF] GridValueSectionedCollecionField displayed a Create button even if listEditable = false;

357.3.0

Added

  • [MDL] Entities can now have a Namespace other than the model's default specified. This groups them in the editor and generates the entity types in that namespace.

Fixed

  • [MDL] Property nodes and section nodes were being deselected when moving them upward in the editor.
  • [WEB] When a ZomboBox lost focus, if it had a selection made by clicking after typing an ambiguous filter, it could reset to the first match instead of the one you picked.

357.2.0

Added

  • [ORM] "Routine errors", a hierarchy of records in the RPC subsystem which classifies common failures such as the server being down or the client being outdated.
  • [TEST] Instagile.Xunit no longer depends on Instagile.Model.
  • [WPF] IShell.TryDisplayRoutineError; shells with support can intercept the routine errors and provide some special-purpose UI with options for the user. TabbedShell provides manual and automatic retries for a backend outage, and a restart button when the client needs updates.
  • [WPF] MarkdownField preview button, which opens a modal to show you the rendered markdown without having to fit into a form.

Fixed

  • [WPF] CalendarView's << Previous Month button was shorter than the other buttons.
  • [WPF] Themes no longer affect context menu text colour.

357.1.0

Added

  • [WPF] MarkdownTextBox and MarkdownField. At the moment, the markdown is only editable as plain text via a popout - we'll evaluate whether that should change.

Changed

  • [ORM] Recalculator has a new constructor parameter for an EntityMetadataDictionary.
  • [ORM] Recalculator will now ignore any requests to recalculate audit entities.

Fixed

  • [ORM] EntityCache failed to create synthetic includes for many-to-many relationships, meaning that if you cached some list of entities which each .Include()d a list of relationship entities, then looked up a single entity from the list, you'd get a cache hit but it wouldn't include the relaetd list.

357.0.1

Changed

  • [WPF] The new themes have changed after feedback:
    • Test and USR, the ones most commonly exposed to users, are now a high-contrast green
    • Staging and SYS are high-contrast yellow
    • Development/DEV is also green, but low-contrast like Production/PRD

Added

  • [WPF] It's now simple to customise or add themes for any environment, although the colours are stringly typed - see Theme.xaml in The.Test.Screens for examples.
  • [WPF] Improved theming of buttons, sections and overlays.

357.0.0

Changed

  • [WPF] Inky now has four built in hue variations based on environment:
    • Production or PRD uses the existing theme
    • Staging or USR has a yellow hue
    • Test or SYS has a red hue
    • Development or DEV has a green hue If you need to totally override these, add ResourceDictionary entries for the The.WPF.Shell.Resources.*Brush keys.
  • [WPF] Shells now use Resources.ShellBackgroundBrushKey instead of SystemBrushes.AppWorkspaceBrushKey.
  • [WPF] Resources.SurfaceBorderBrushKey has been renamed to ShellBorderBrushKey.
  • [WPF] Options.AppName now includes " (Environment)" if Options.Environment isn't Production or PRD.

Added

  • [ORM] Unloaded collections now support .Cached() queries (This would execute queries successfully before, but not through the cache).
  • [WPF] In TabbedShell, you can double-click on the application title to switch to the Production theme.
  • [WPF] The existence check done when opening a Recent Item from a pin is now cached.

356.3.0

Added

  • [ORM] New experimental option Options.CalculateOnServer. When changed to true for some instance of the framework, calculated properties and On(Saved|Saving)[Async] hooks will not run; instead, SavePlanner will set a flag which requests that the server execute them after processing entity updates. The current implementation of server-side calculation is unsophisticated, and will break applications which assume that these calculations or hooks run on the client side - however, it can greatly improve the performance of saves when the application server is closer to the database server than to the client.

Fixed

  • [RPC] WebEndpoint wasn't reusing HTTP connections correctly. This was a major performance problem - repeating a TCP+TLS handshake added 130-150ms to the cost of every server call on the public internet.

356.2.0

Added

  • [SQL] IDDLDialect implementations specify when their setup scripts were last changed. MigrationRunner doesn't rerun them (which can be quite slow) if a db's last recorded run of that batch was more recent.

Fixed

  • [WPF] Calendar filter entries weren't respecting read permissions.

356.1.1

Fixed

  • [WPF] Fix incorrectly copying thumnail when copying image from <ImageControl>.

356.1.0

Added

  • [MODEL] XML comments in .theModel files are preserved by representing them as a CommentV1Event in the history. IEvent processors ignore this event unless their purpose is to present events for display.
  • [MODEL] The model editor displays a list of events affecting a selected node to the right of that node's settings.
  • [WPF] The ability to filter entry sources on the calendar, using preferences to remember the user's choices.

Fixed

  • [DOC] Documents couldn't be uploaded if they were locked by another process.
  • [WPF] Fixed a number of binding errors that had accumulated.

356.0.1

Fixed

  • [WPF] Yet another edge case in ZomboBox filtering when everything is high-performance or cached - its original design never really worked when everything happened on the same event-loop tick.
  • [WEB] Under high load, core IServices instances could be shared between web IServices instances. This was the root cause of at least one bug - sharing RPC implementation instances between separate calls.

356.0.0

Added

  • [WPF] If Options.ForcePasswordChangeOnReset is set, then when an admin changes a user's password or creates a new user account, it will set a temporary password.
  • [WPF] A change password screen now appears when a user successfully logs in with a temporary password.

Changed

  • [ORM] IAuthentication.EncryptDataAsync now requires state (typically key material) created by PrepareSessionAsync. PrepareSessionAsync() may return an alternate value explaining why encryption cannot occur.
  • [ORM] PasswordAuthentication.SetUsernameAndPasswordAsync has a new parameter forcePasswordChange. If true, it sets a temporary password. This forces the user to change their password on their next login.
  • [ORM] GetUserPasswordSalt RPC is now anonymous.

Fixed

  • [WPF] ZomboBox: outdated filtering results were being used when the user typed at a pace which repeatedly triggered filtering.

355.2.6

Added

  • [WEB] Debug-level logging for the process of resolving RPC implementations that use DI, which may be buggy (category The.Web.Composition.DependencyInjection).

Fixed

  • [ORM] Cache bug: when a query's count was cached but not its corresponding elements (for example, on criteria screens), and considered Fresh (for example, due to being persistent reference data) then .Cached() queries which requested fresh data would return an empty list instead of fetching the constituent elements. This frequently affected but may not have been limited to EnumSectionedCollectionField.

355.2.5

Fixed

  • [ORM] ThenInclude() after a skipped Include() wasn't itself skipping inclusion.

355.2.4

Added

  • [ORM] Include() and ThenInclude() now check entity authorization before including related entities. By default, unauthorized includes are silently skipped; pass throwIfUnauthorised: true to throw a SecurityException instead.

355.2.3

Fixed

  • [SQL] TransienTentityStore NULL propagation bug which prevented this pattern from executing correctly:
    .Where(x => x.Ref != null)
    .Select(x => x.Ref)
    .Where(y => y.Attribute.Property == whatever)
    

355.2.2

Added

  • [WPF] ZomboBox: in the dropdown options, text matching the filter is highlighted.
  • [WPF] ZomboBox: when UpdateItemsSourceCommand is null, filtering is done internally based on DisplayMemberPath or the item's ToString().

355.2.1

Fixed

  • [WPF] ZomboBox bugfixes - inexact matching for textual reselection, synchronous binding when the filtering command is fast (due to caching), present a dropdown even when not filtering.

355.2.0

Added

  • [ORM] Error handling throughout the reminder subsystem.
  • [WPF] IconButton.StrokeThickness attached property for IconButton style.
  • [WPF] Display of reminder errors, including reminders missing on or unexpected provided by the backend.

355.1.0

Added

  • [ORM] New method TransientCache.Evict(), which can be used to manually clear out the cache. Useful for testing, possibly not otherwise.
  • [WPF] Dispatcher.SafeInvoke extension method, which doesn't block when the application shuts down - rare in typical use, but common in unit tests.

Deprecated

  • [WPF] Dispatcher.Invoke is now warned against via analyser. There's a codefix to convert to SafeInvoke, or you can suppress THE005 if you really want to Invoke for some reason.

Fixed

  • [ORM] Reminders in a GUI used to be effectively Distinct() because they were loaded with Freeze(). Since v353, this is no longer true; furthermore, it's never been true in the server-side cache, so counts were off. Now reminder queries are always wrapped in Distinct(), restoring GUI list behaviour and fixing the count.
  • [ORM] Eviction could break cache coherence by leaving query entries in the cache but removing the entity entries upon which they depended. The eviction bug is fixed, and EntityCache can now recover from cache incoherence if it does happen in some other way.
  • [WPF] EntitySectionedCollectionField wasn't correctly marshalling updates from the cache onto the main thread. This is probably the cause of the "no checkboxes visible" bug that some people have reported seeing in relationship options criteria.

355.0.0

Added

  • [ORM] Concurrent context modification detection. If an entity context is accessed by multiple threads concurrently, a warning-level message will be logged; with trace-level logging, stack traces will be included. This behaviour can be configured with Options.ConcurrentMutation - set ConcurrentAccessMode.Error to throw an exception, or .Enabled to suppress warnings.
  • [ORM] TransientEntityStore now supports connections from clients using different offsets on the same machine - this is mostly for the sake of tests which rely manipulating TimeZoneInfo.Local.
  • [ORM] Implicit conversion from RelationshipInfo to RelationshipPath, which is a common operation now that we have more include-based APIs.
  • [ORM] Cache: synthetic includes can now be generated for collection loads (which means that you get click-through caching of includes for the elements).
  • [WPF] Grid screen default preloads, using the same heuristics as List/Display and the same API as List.
  • [WPF] CellReferenceControl now supports caching.

Changed

  • [BLD] The default value of <InstructionsPath> is now ".github/instructions". This reduces clutter, and allows per-path .instructions.md files to reference framework instructions without using "../".
  • [LOG] Builder.ConfigureLogging() now uses ILoggingBuilder, supporting common Microsoft.Extensions.Logging providers. It won't work for providers that genuinely require some ASP.NET core services from DI (unless you actually are using ASP.NET Core).

Deprecated

  • [WPF] GridController.GetPreloadedRelationships() and GetPreloadedPropertyPaths() - use GetPreloadedRelationshipPaths() instead.

Fixed

  • [BLD] Fixed many flaky tests, with causes including timing, threading and wrong assumptions.
  • [ORM] Fixed cache failing to re-query M:N join tables for ThenInclude chains where the M:N relationship is not the first step. This resulted in unloaded collections from cached queries with patterns like .Include(x => x.Items).ThenInclude(y => y.EvenMoreItems).
  • [ORM] Improved recursive lock prevention in the cache subsystem, in particular affecting the EntityCache.Add(IEntityQuery) overload.
  • [ORM] Missing updates when a Cached() result was created long before subscribing to changes.
  • [ORM] RPC session renewal was asserting against negative deadlines, but this can happen when clock skew results in an overflow.
  • [ORM] InvalidOperation bug when using caching complex list queries with SelectMany() followed by Include() sequences.
  • [WPF] Made ScreenTemplate more resilient to duplicate field labels.
  • [WPF] Eliminated a sync read in EntitySelectorModel.
  • [WPF] Made VirtualisedList load data on the dispatcher to prevent it from concurrently accessing the context of some screenmodel.
  • [WPF] Fixed Unsound behaviour in relationship fields that use EntitySelectorModel. The selector was loading data from the screen's main context on a background thread; this misguided attempt to improve performance works for generated UI patterns, but it means that applications with custom UI that works on the dispatcher (as it should) will race with the selector load, violating context thread-safety. This bug has been present in latent form for years, but it's usually covered up in practice by preloading.

354.6.4

Fixed

  • [BLD] Fixed incompatbility with nuget packages that add extra dlls in their build scripts, such as Microsoft.Web.WebView2

354.6.3

Fixed

  • [BLD] Instruction .md files still showed up in Solution Explorer, still at the wrong location.
  • [ORM] Improved space/time performance of .Include() slightly.

354.6.2

Fixed

  • [ORM] Calling .Include() with the same value (or overlapping RelationshipPath values) twice on collections threw an exception instead of deduplicating.

354.6.1

Fixed

  • [BLD] Instruction .md delivery wasn't transitive - if you PackageReferenced Instagile.Web, you didn't get assets from Instagile.Web.Client.
  • [BLD] Instruction .md files showed up in Solution Explorer, at the wrong location (within each project!).

354.6.0

Added

  • [WPF] Numerous NRT annotations. This may result in new warnings for programs with <Nullable>enable</Nullable>; hopefully it will also result in fewer NullReferenceExceptions.
  • [WPF] "Reset Columns" menu item to Lists and Grids to reset the columns to the model default.

Fixed

  • [ORM] Extended Include() support wasn't handling component interfaces correctly.
  • [WPF] DisplayController was trying to set SaveCommand.IsEnabled even if SaveCommand was null.

354.5.1

Fixed

  • [WPF] Data tearing and inadequate error-handling in CellCollectionControl when a list received overlapping cache invalidations quickly.

354.5.0

Added

  • [ORM] Moved the temporary control-disabling effect of ContentModel.IsEditableRW to a new property IsEnabled. This allows Display screens to suppress editability without requiring all field overrides to adapt to a new mutability contract.

354.4.0

Added

  • [ORM] Restored public accessibility of IEntityQueryProvider.CreateQuery(), which was made internal back when FilterLevel was also internal.

354.3.0

Added

  • [WPF] New property for DisplayOptions and ListOptions: PreloadRelationshipDepth. The default is 1; if reduced to 0 it will suppress relationship preloading, and if increased above 1 it will recurse through value relationships.

Deprecated

  • [WPF] ListController.GetPreloadedRelationships() and GetPreloadedPropertyPaths() - use GetPreloadedRelationshipPaths() instead.

354.2.2

Fixed

  • [BLD] Excessive file copies when using an Instagile package that provides contentFiles along with a non-Instaigle package that also provides some.

354.2.1

Fixed

  • [WEB] Packaging error in Instagile.Web.Client frontend assets.

354.2.0

This release includes experimental LLM instructions files for the main API packages. They're just structured documentation, so technically this is also useful to humans, but the style is terse and sample-oriented in a way that suits model context. Packages' instruction files will be dumped in the .github/ directory by default (configurable using properties InstructionsPath and InstructionsEnabled). The idea is to reference them from personal or codebase rules files, like in this example:

**Note:** For detailed information about using the Instagile framework (all `The.*` namespaces), refer to the relevant guide based on what you're working on:
- **[Instagile/orm-guide.md](./Instagile/orm-guide.md)** - Core framework, entities, querying, calculated properties, RPC, authentication (use when working with `App.Model` or any entity/business logic code)
- **[Instagile.WPF/gui-guide.md](./Instagile.WPF/gui-guide.md)** - Desktop UI customization, screen controllers, fields, grids, menus (use when working with `App.Desktop` or WPF screens)
- **[Instagile.Web/backend-guide.md](./Instagile.Web/backend-guide.md)** - Background jobs, web initialization, ASP.NET Core setup (use when working with `App.Web/Program.cs` or jobs)
- **[Instagile.Web.Client/frontend-guide.md](./Instagile.Web.Client/frontend-guide.md)** - Blazor components, design system, CSS theming (use when working with `App.Web` Blazor pages/components)

Added

  • [ORM] .Include() now supports many-to-many relationships. When used together with .Cached(), the many-to-many ID pairs themselves aren't cached yet, so there will always be at least one store query to load them.
  • [ORM] RequestOptions.StaleBefore, which requests revalidation (ultimately controlled by ReadPolicy) for otherwise-fresh data that dates to before a local timestamp.
  • [WPF] Search screens and sub-search criteria use StaleBefore to guarantee an initial revalidation.

Changed

  • [ORM] ReadPolicy custom delegates now receive a maxAge parameter indicating cache clients' opinion on when data should be considered stale. (Most of the time it will be TimeSpan.MaxValue, leaving freshness up to policy.)
  • [ORM] CacheResult update-handler delegates now receive a nullable update; if it's null, the update is a successful revalidation, with no actual change to cached data.

Fixed

  • [WPF] LIRF/VIRF/VSRF async lazy-loading didn't handle the possibility of someone else loading the data first. The fields are now guaranteed to actually finish loading.

354.1.1

Fixed

  • [ORM] .Cached(Requirements: Uncached) queries didn't successfully force a refresh - and worse, if there was a partial cache hit, the stale entries were refreshed, meaning includes didn't latch in time.
  • [WEB] After recent Include() improvements, <EntityListView> generated bad SQL when displaying unloaded collections that contained relationship columns. Now it uses Include(), which fixes the SQL and improves performance.

354.1.0

The framework now supports (but does not require) .NET 10, and requires the .NET 10 SDK to build.

Fixed

  • [RPC] WebEndpoint streaming is now even more async, which is required by Blazor in .NET 10.
  • [WEB] Instagile.Web frontend assets are accessible to MapStaticAssets(), which is required by Blazor in .NET 10. They still work with the older UseStaticFiles().

354.0.2

Fixed

  • [WPF] ListController internal concurrency issue re-fixed due to a typo.

354.0.1

Fixed

  • [ORM] Cache subset entries created by reordering already-cached entities in memory had the wrong versions for invalidation.
  • [ORM] Cache fetches which batched together Count and ToList queries were subject to a race condition causing an exception. This could happen even in a single call when using the pattern .Include().Cached().CountAsync().
  • [WPF] LookupInlineReferenceField just didn't work at all.
  • [WPF] ListController internal concurrency issue when existing rows were updated due to a cache invalidation. Probably wasn't observable, but bad for performance.

354.0.0

Added

  • [ORM] Query caching system, disabled by default. The short version is that calling .Cached() on an IEntityQuery<T> will give you access to new operators which return a CacheResult, containing data of varied freshness and a subscription mechanism. For more information, see public/cache.html.
  • [WPF] Integrated query caching into UI components. If the cache is enabled, most screens and fields will load data from/through/into it with appropriate policies.
  • [WPF] Eliminated sync reads used by fields presenting EntityReferenceProperty. If a reference isn't preloaded or cached, it will be loaded asynchronously with a placeholder.
  • [WPF] VirtualisedList optimisations:
    • metadata cleanup, meaning memory usage is bounded no matter how much you scroll
    • preloads are included in the page query, halving roundtrips
    • more tuning available in the new Options.Virtualisation
  • [WPF] virtual ListController.GetPreloadedRelationshipPaths(). The base implementation defers to the existing GetPreloadedRelationships() and GetPreloadedPropertyPaths() methods, but if you need something more complex you can override the higher-level method for direct control.
  • [WPF] SearchDelay properties (Options, ZomboBox, CriteriaController) etc are now nullable - it may be beneficial to remove the delay when using caching. The default is still 400ms.

Changed

  • [ORM] IEntitySet<T> has new members ResultState CacheState and LoadCachedAsync(). Custom implementations will need to implement, delegate or noop them.
  • [WPF] Search screens no longer do freezing - they produce IEntityQuery<T> synchronously instead of IFrozenQuery<T> asynchronously. Round trips per criteria-change are halved.
  • [WPF] List and Search screens' RefreshAsync() functions have a new optional parameter bool force = false. If set to true (as the built-in screen commands do) it performs an explicit cache bypass. Display screens also bypass cache on refresh, but it's mandatory - there is no reason to refresh one other than to get new data.

Deprecated

  • [WPF] DisplayController.LoadEntityAsync(). Overriding this method still works, but will disable caching. To replace it, use some combination of CreateLoadQuery() (new), OnLoading[Async]() (new), and OnLoaded[Async](); or, none of the above. CreateLoadQuery() includes editable related data by default, and when caching is enabled it's more efficient to not load unrelated data (like entire reference data tables).

353.1.0

Added

  • [ORM] Overload IEntitySet<T>.LoadAsync(RelationshipPath[]), accepting related data to load along with the set. Query-based sets apply includes via .Include() before loading; in-memory sets (including sets that are already loaded) load the extra relationships separately.
  • [WPF] Virtual method ListController<T>.GetOrderedQueryAsync(), which allows subclasses to customize list ordering beyond what's possible with column selection.
  • [WPF] Virtual method GridController<T>.GetPreloadedRelationships(model), similar to the ListController equivalent except that it works using the new entity set method above.

353.0.0

Added

  • [ORM] EntitySet<T>, an IEntitySet<T> implementation representing a whole database table. Unlike most sets, it has a SaveAsync() method for updating the DB.
  • [ORM] IEntityQuery.Include(RelationshipPath) and ThenInclude(RelationshipPath). This is like using chained lambdas, but supports passing through collections as well as references.
  • [ORM] Measure methods on IEntityInfo and EntityFactory. These can be used to count the total closure of a Row in bytes, or estimate it without an actual instance.
  • [ORM] EntityReferenceProperty<T>.AsUnloaded() - this gives you a query which can be used to load the reference, like the existing EntityCollectionProperty<T>.AsUnloaded().
  • [WPF] Content screens' IsEditable property, when false, now disables all controls within the screen. Previously it did various editability-related things, but didn't actually prevent editing!
  • [WPF] Content placeholders now set IsEditable to false.

Changed

  • [ORM] Version attributes are now represented as an unsigned 64-bit number (ulong) in memory. Their database-specific types haven't changed. This makes it easier to extract and compare version numbers of entity instances.
  • [WPF] List and Grid screens have been refactored to simplify construction, continuing their divergent evolution. Previously, both ListController<T> and GridController<T> required a Func<Task<IFrozenQuery<T>>> - an awkward type trying to unify various usecases, while still not being fully general - as it had no IEntityContext parameter, callers still had to manufacture their own queries.
  • Grids now require an IEntitySet<T>, which can be loaded or unloaded. All built-in uses of grid were using one already, and GridController did internal casts to actually use its features.
  • Grids' Refresh command and API have been removed. Grids are designed for editable data (like Content screens) which may change by events or clones but not re-loading.
  • Lists now require an IEntityQuery<T> and optional count. You can supply a frozen query or entity set to use their built-in count; otherwise, it will be loaded when necessary.
  • Lists' RefreshAsync API has new overloads which accept a query (or set, etc) to update with new data. This replaces the usecase of the Func parameter wherein it could return a new query if refreshed - this worked, but required components that embedded lists to allow them to drive the refresh of the outer screen or field.

Fixed

  • [ORM] .Include() would throw when used on an in-memory list (someList.AsQueryable().AsEntityQuery().Include()). Now it's just a no-op.
  • [WPF] Fixed an bug where error tooltips could display when validation was suppressed.
  • [WPF] Fixed GridModelBase.IsEditableRW not being respected by field cells if changed after row creation.
  • [WEB] Race condition led to blank titles when <AsyncPage> used in <ResponsiveShell> with a GetTitle callback but no other use of context.

352.3.0

Added

  • [WPF] ListOptions.PrefsNamespace, which can be used to give a list instance preferences independent of other same-entity lists.
  • [WPF] RemindersController sets a list prefs namespace, so using separate reminders sidebars within a multibar will give them different preferences.

Removed

  • [ORM] IQueryable.Include() - we don't use IQueryable anymore except for compatbility with non-store providers.

Fixed

  • [ORM] IEntityQuery.Include() now supports chained references again (which was broken by 352.2), as does the new .ThenInclude():
    var dogWithEverything = Dog.Query(context).Include(d => d.BestFriend.Owns);
    var catWithEVERYTHING = Cat.Query(context).Include(c => c.Enemy.BestFriend).ThenInclude(h => h.Owns.Sheep);
    
    Unlike in v351 and below, it's not necessary to separately include BestFriend; the chained include will load all the data along the way. If separate includes do exist, they'll be deduplicated, so this change is backwards compatible.
  • [ORM] IEntityQuery.Include() didn't do anything on IEntitySet collections. Now it works; when the collection is unloaded the includes will be batched as usual, and when it's loaded then only the includes will be executed, bringing them into memory to accompany the collection elements.

352.2.0

Added

  • [ORM] New utility class CollectionDictionary, a multimap between keys and collections of values.
  • [ORM] .ThenInclude() query operator, allowing reliable chaining of eager-loading inclusions. Examples:
    var dogWithEverything = Dog.Query(context)
        .Include(d => d.BestFriend) // a Human
        .ThenInclude(h => h.Owns)   // the Human's farm
        .Include(d => d.Frenemy);   // a Cat - linked from the original Dog
    
    var variousFarmAnimals = Farm.Query(context)
        .Include(f => f.Dogs).        // a collection
        .ThenInclude(d => d.Frenemy); // a reference - linked through the collection
    
  • [WEB] FocusChanged event callback to <TextField>.

Changed

  • [SCM] Scrambled date/time types are now guaranteed to have a changed value.

352.1.0

Added

  • [SQL] IDatabase.Batch[Async](). These methods do explicit statement batching; code like
    something = database.Query(
      "INSERT @p0; SELECT Bar; SELECT Baz", 
      reader => 
      {
        reader.NextResult();
        returnreader.ReadBaz();
      },
      new DBParameter("p0")
    );
    
    can now be written as
    database.Batch([
      new("INSERT p0", new DBParameter("p0")),
      new("SELECT Bar"),
      new("SELECT Baz", reader => something = reader.ReadBaz())
    ]);
    
    With explicit batching, you don't need to combine all the parameters and reader functions.
  • [SQL] New package Instagile.PostgreSQL, containing PostgreSQLDatabase and PostgreSQLEntityStore. The feature set is the union of Instagile.SQLServer and Instagile.SQLite, apart from the following limitations:
    • While all contract tests and migration tests pass, it hasn't had any real-world usage. There will be bugs.
    • PostgreSQL only supports positional parameters ($1), so PostgreSQLDatabase can't do implicit batching. The new explicit batching works, and this is what PostgreSQLEntityStore uses.
    • For timezone support, we've included a hardcoded mapping from Windows time zone names to IANA tzids. This will need to be updated if new timezones are added (civil war, the return of Atlantis, etc).
    • There's no PostgreSQLDocumentStore (yet?).
  • [WEB] FocusChanged events to <ListBox>, which <ListReferenceField> now implements.

Changed

  • [BLD] framework.sln now builds with dotnet build, and framework.xplat.sln has been removed. Visual Studio is still necessary to build all features; specifically, MS Access import support and VSIX extension test-deployment won't work cross-platform.
  • [BLD] dotnet test now works on framework.sln (apart from MS Access import tests), but be careful: this includes Instagile.WPF.Tests, which can take a long time.
  • [BLD] Running the new Instagile.PostgreSQL.Tests requires Docker.

Fixed

  • [SEC] DBKeyProvider was incorrectly caching public keys resulting in reinitialized PKI tokens being unable to login.

352.0.0

Added

  • [ORM] Options.TimeZone and Options.TimeZoneId. These settings control the timezone used for Instants and RelativeDates (see below). Internally, they're both wrappers around Options.TimeProvider, which can be set directly for testing. The current timezone can be changed using Services.Persistence.SetTimeZone() and ResetTimeZone().
  • [SQL] TimeSpans are now better supported in queries - TimeSpans returned by date calculations work, as does arithmetic and passing in TimeSpan constants. (It was already possible to pass TimeSpans to supported date methods, but only as client-evaluated parameters).
  • [SQL] FunctionName.AbsoluteValue, representing SQL ABS() in QIR.
  • [SQL] Predicates.Like() is back after a few years off. This time it's more reliable, working in all entity stores and supporting both % and _ wildcards (the only part of LIKE that's ANSI SQL).
  • [SQL] The.Search.RelativeDate. Like The.Search.Predicates, RelativeDates are query-helper expressions which are evaluated in the datastore. RelativeDate.Today or RelativeDate.Now can be used in specs or queries - they refer to the current date or time of execution in the client's timezone. Offsets are also built in: var nextWeek = RelativeDate.Today.AddDays(7) creates a constant which can be reused (for example, in a set of reminders).

Changed

  • [ORM] Instants are now presented in configured Options.TimeZone, rather than being presented in the machine's timezone but inconsistently converted to the DisplayTimezone in some UI elements.
  • [ORM] The Tenancy parameter of IEntityStore.ExecuteReads[Async]() has been replaced with a QueryConfig parameter. This contains both the tenancy restriction and the client's timezone id.
  • [WEB] DefaultListSpec no longer requires a timezone constructor parameter.

Removed

  • [ORM] Options.DisplayTimezone, which has been replaced by Options.TimeZone.
  • [ORM] InstantExtensions, which contained conversion functions that have been replaced by Options.TimeZone.

Fixed

  • [MDL] The editor "Copy entity" command was burning-in defaults for captions and plurals, so copied entities would end up with a name like "Foo Copy" but a plural of "Foos".
  • [SQL] string.Contains(), string.EndsWith() and string.StartsWith() didn't work correctly in TransientEntityStore when the argument was not a literal string.
  • [SQL] Exactly-equal date comparisons between columns and calculations never matched in SQLite.
  • [SQL] Subtracting instants from instants produced invalid T-SQL in Instagile.SQLServer.
  • [ORM] Instant values were being represented in local time during read and write ops. This had a small performance cost, and could produce incorrectly zoned results when .Select()ing an instant using TransientEntityStore.

351.0.0

Changed

  • [WPF] Create screens now have an optional initialiser delegate specified separately to their factory delegate; errors in the initialiser are non-fatal. They can be made fatal again with CreateOptions.RequireCompleteInit. ScreenService.CreateCreateController() overloads with an init parameter have been changed to use this feature, and new overloads have been added which allow supplying the factory and init delegates separately.

Fixed

  • [WPF] Global surface notifications were being hidden behind the main application content when using TabbedShell.

350.7.1

Fixed

  • [ORM] TransientEntityStore was throwing when trying to perform date arithmetic on NULL.
  • [WPF] ScrambledDatabase component screen overrides would try to show an error notification from the thread pool when no scrambled databases have been configured, rather than doing so from the dispatcher. This would cause a confusing error to be displayed.

350.7.0

Fixed

  • [ORM] EntityExtensions.DeleteAndCascadeAsLoaded would fail to prune value relationships where the other side was not lookup.
  • [ORM] GraphNavigation.GetGraphLoadOperations would fail to generate read ops from store queries when the query type was IEntity and the expression type differed from the source entity type. This also affected queries generated by QueryBatch.

Changed

  • [ORM] Scrambling will now use zero if a scrambled long is out of range.

350.6.0

Fixed

  • [ORM] Query translation now supports:
    • Enumerable-like methods on MemoryExtensions, such as this ReadOnlySpan<T>.Contains(),
    • Implicit conversions to Span<T>/ReadOnlySpan<T>, and therefore
    • C# 14, which adds an implicit conversion from array to Span<T> to the System namespace.
  • [WEB] Serialisation of references in EntityState<T> was broken when using JSON (WrapPrerenderState = false).
  • [SEC] ReadOnlyAuthorisation GetDefaultPermissions and GetRolePermissions were calling back on themselves resulting in a stack overflow.

350.5.1

Fixed

  • [BLD] The solution now builds under C# 14.
  • [BLD] Instagile 2022.vsix is now marked as compatible with Visual Studio 2026. It still works in 2022 as well.
  • [SEC] When using client-server authentication, trusted identities (that is, the identities of trusted principals) were not undergoing authorisation checks on the backend. Now they are; by default, an identity with Realm.Trusted won't be given any special status. A backend can still choose to trust the client's assertion of trusted status if desired, by inspecting the realm of the identity passed to GetIdentityRoles().

350.5.0

Added

  • [ORM] Mid-level serialisation API The.Persistence.InertGraph, which can serialise a tree of entities and restore it into a new context.
  • [ORM] The.Persistence.Row and the ValueBoxes within now support System.Text.Json serialisation.
  • [WEB] EntityState<T> and QueryState<T> use System.Text.Json directly instead of serialising to MessagePack and then wrapping the result in JSON. This should be faster, but if it isn't - or has bugs - you can revert to the old behaviour by setting Options.RPC.WrapPrerenderState to true.

Fixed

  • [DOC] Document endpoints now handle assertions for an entity that doesn't exist (by returning 404).
  • [ORM] IEntityQuery.ToHashSet() was erroneously named ToHashSetAsync(), preventing callers from using the real async version unless they had a cancellation token.
  • [WPF] The visibility of hero sections wasn't be invalidated by ContentModel.InvalidateSectionVisibility().
  • [WPF] Fixed rare race to access Model in DisplayController.InitContentAsync before it has been set.
  • [ORM] Fixed translation of DateOnly comparisons where the month abbreviation was 4 characters long (i.e. Sept).

350.4.0

Added

  • [WEB] Added optional <BoundDependency FallbackContent>, which will be displayed if the dependency is not registered.
  • [WEB] When running on .NET 9+, <BoundTask> has a new parameter bool Prerender = true. If set to false, the binding won't be loaded during prerendering - it will just display the <LoadingContent>.
  • [WEB] When using AddTheFramework(), injected service IDocumentLinkGenerator, which can be used to produce server-side download URLs or image srcs.
    • Doclinks now support the document security model feature - when enabled, the generator produces more links which include the required entity access assertion.
    • Image doclinks and GetSourceLink() support query parameters to request a thumbnail.
  • [WEB] New component <DocumentImage>, which produces an based on an ImageDocument. Does no async I/O, allowing browser image caching to work. <ImageCell> in lists will use <DocumentImage> when a backend is available.

350.3.0

Fixed

  • [WEB] JobBase.CancelRun() wasn't cancelling runs due the wrong CancellationToken being cancelled.

Added

  • [WEB] Running jobs can now be cancelled from <JobControlView>.

350.2.1

Fixed

  • [WEB] AdminOnly in list columns now applies to preloads as well as visibility, so that the UI doesn't try to load relationships for which it might not be authorised.

350.2.0

Added

  • [WEB] The AdminOnly flag is now supported in lists. CellSpecs created from PropertyInfos create ColumnModels with an IsAdminOnly property, and <EntityListView> only displays these columns to admins. The existing support for AdminOnly in <EntityEditViews> is now more efficient due to using the same mechanism.

350.1.0

Added

  • [WEB] <ModalRegistration> now cascades itself so that content inside the modal has access to its API.

Fixed

  • [WEB] Navigating away from a page with a modal open didn't actually cause the modal UI to go away, meaning you couldn't see the new page.
  • [WEB] Reloading a page with an open modal and then dismissing it resulted in an empty command bar when using <SidebarShell> or `.
  • [WEB] Commands are now present on the first render of a <Page>, reducing flicker.
  • [WEB] Use of the File System Access API for document and export downloads is now disabled by default, because it can be unpredictable on intranets with network home drives. To re-enable it, set Options.UseFileSystemAccessApiForDownloads to true in your Program.cs or Startup.cs.

350.0.0

Added

  • [WEB] Generic variants of ScaffoldService.CreateEntityAsync() and LoadEntityAsync() which don't require an IEntityInfo.

Fixed

  • [WEB] <ListCollectionField> was not using editspec create functions.

350.0.1

Changed

  • [WEB] IEditSpec.CreateEntity() is now CreateEntityAsync(). DefaultEditSpec.CreateEntity() has been preserved for convenience and backwards compatibility.

Added

  • [WEB] List rows can be given MessageLevel-based colours using IListSpec.GetLevel(row).

349.1.0

Security

  • [WEB/WPF] Updated ImageSharp to fix CVE-2025-54575, a denial-of-service vulnerability when loading maliciously crafted GIFs.

Added

  • [DOC] NoDocumentStore accepts an optional constructor parameter to override its error message.
  • [SQL] Improved support for date arithmetic. The AddDays() method of DateTime and DateTimeOffset was already supported; it's now joined by:
    • AddHours()
    • AddMinutes()
    • AddSeconds()
    • AddMilliseconds() (subject to RDBMS capabilities and column types)
    • Add(TimeSpan)
    • Support for the + and - operators combining a datetime[offset] and a timespan.
  • [WEB] When using a browser that supports the File System Access API (for example, recent Chromium-based ones), documents are streamed from store to the client's disk without being buffered anywhere.
  • [WEB] <BarTable> is now a command host - you can use ` inside it and the commands will be displayed in the top right. At the moment, command labels are interpreted as icon names rather than text. This will be made optional with a later breaking change to command construction
  • [WEB] For users with export permission, <EntityListView> displays a download command which exports the contents of a list as CSV. This uses the same zero-buffer streaming as documents.

Fixed

  • [WEB] <ListCollectionField>'s modals now calculate parent entities like WPF does, so that you can see parent text in multi-level modals.
  • [ORM] Cloning separately-loaded subsets containing !IsPresent collections over an existing copy could leave relationships half-unloaded.
  • [WPF] Manual calendar entries could be created by user's who didn't have write access to the ManualCalendarEntry entity.

349.0.1

Fixed

  • [WEB] Modal routing couldn't handle an edge case where a modal was removed by rerendering and then an immediate redirect was done to the modal-less URL of the same page. (This sounds like a weird thing to do, but it's basically "logout and force reload").

349.0.0

Added

  • [WPF] LSCF and LIRF have a new CreateOverride option/parameter which works like SearchOverride, customising the behaviour of the [+] button provided by their internal EntitySelector.

Changed

  • [WPF] Lists and grids now show the header even if there are no rows. This can be disabled with ListOptions.AlwaysShowHeader and GridOptions.AlwaysShowHeader.
  • [WPF] IntegerToHeaderVisibilityConverter is now BooleanToHeaderVisibilityConverter.

348.3.1

Fixed

  • [WEB] <DateBox> and <DateTimeBox> data-binding fixes. Behind the scenes: our format conversion was too reasonable - web browsers set the DOM value attribute to a string they wouldn't themselves accept in HTML! These widgets now use quite lax parsing on the browser->component transition, relying on the other side of the round-trip to fix it up again.
  • [WPF] Don't show "Delete saved credentials" button on password login if AllowSavedCredentials is false.

348.3.0

Added

  • [WPF] ConfigureOpenFileDialog property to FileField and ImageField to allow applications to customise the OpenFileDialog that is shown when uploading a file.

348.2.0

Added

  • [WEB] Schedule.GetNextOccurrence which returns the date and time of the next occurrence of that schedule from a given starting date and time.

Fixed

  • [SQL] Count() after Take() without any other filtering did not nest the Take()n expression in a subquery, and produced excessively-concise SQL without a TOP clause.
  • [WEB] ScheduledJobBase would sometimes run jobs before their scheduled time which could cause the job to run multiple times in quick succession.

348.1.0

Added

  • [EML] AzureMailer's connectionString parameter is now nullable; if not set, the mailer will produce errors rather than sending mail, but it won't throw an exception at startup - which is more dangerous.
  • [SEC] User registration requests send the current Windows user's display name.

348.0.0

Added

  • [WPF] CreatePKIAccountScreen for registering user accounts with a PKI token.

Changed

  • [WPF] Breaking: Changed constructor parameters for PKILoginHandler.
  • [WPF] PKILoginHandler now provides optional support for user registration.

347.2.3

Fixed

  • [WEB] <BoxArea> had lost its ability to scroll.

347.2.1

Fixed

  • [EML] Fixed mail sender addresses being configured in two separate places.

347.2.0

Added

  • [EML] IServices.Mail is now available at the Instagile.nupkg level (although there aren't any non-web IMailer implementations yet).

347.1.0

Added

  • [WEB] IServices.Mail, a new abstraction for sending emails. To use it, you'll need to RegisterMailer() at composition time as well as setting Options.SenderAddress and Options.TestRecipientAddress.
  • [WEB] AzureMailer, which sends emails using Azure Communication Services. Requires a connection string.
  • [WEB] <SecondsTimeField> and <SecondsDateTimeField>, which present Time/DateTime attributes with a resolution of seconds instead of minutes. They aren't used by default, but can be enabled for a field or application-wide using an IEditSpec.

347.0.0

Added

  • [WEB] Date/time widgets revamp:
    • <TimeBox> and <DateTimeBox> widgets have a new parameter Step which lets you set the time resolution (minutes, seconds or milliseconds).
    • <DateTimeBox> and display as a single input box that handles both date and time.
    • <DateTimeBox> now has IsReadOnly (which was already available on <DateBox>, <TimeBox> and <InstantBox>).
  • [SEC] Added two properties to PKIAuthentication which can be used to provide a different ambient identity, such as a Windows identity.
    • UsernameProvider which should be used on the client to override the username.
    • LookupAccountByUsername which should be used on the backend to lookup user accounts by matching username, rather than by matching database key name (the default for PKIAuthentication).

Changed

  • [WPF] Removed environment constructor parameter from PasswordLoginHandler.
  • [WPF] PasswordLoginHandler now supports username providers. If a username provider is specified, it will show the username field in a read-only state with that username.

Fixed

  • [SQLITE] Emitter didn't support TimeOnly constants, which broke some features when using AttributeType.Time.
  • [WEB] Fixed error from missing IDocumentLinkGenerator service registration when calling MapTheFramework with document routes disabled and framework prerequisites not having been registered.

Removed

  • [WPF] Removed PasswordOnlyLoginHandler, PasswordOnlyLoginModel and PasswordOnlyLoginView, all of which has been rolled into the PasswordLoginHandler and such.
    • Applications migrating to PasswordLoginHandler should make sure to set ExternallyProvidedUsername on any customised PasswordLoginModel.

346.0.0

Added

  • [WEB] Added new optional parameter to MapTheFramework and to the constructor for EndpointOptions to allow applications to disable all routes by default and then opt-in on an individual basis.
  • [WPF] Added the ability to right-click and copy an image.

Changed

  • [WEB] Controller-style routes are now disabled by default. They can be re-enabled by setting EndpointOptions.IncludeControllerStyleRoutes to true in the configuration delegate provided to MapTheFramework. These routes will be removed in a future release so migrating to use the new RPC routes is recommended.

345.1.0

Added

  • [WEB] Basic document/image links using DocumentAccessAssertion.Unspecified. There's no frontend available yet, but documents can be downloaded from the endpoints _the/doc/file/{id}/{filename?} and _the/doc/image/{id}/{filename?}. Document security will be checked if enabled, but there's no way to specify an access rule yet, so it only works for globally accessible documents.

Fixed

  • [ORM] Identity was comparing Usernames case sensitive which caused issues with RoleCache invalidation when logged-in user and UserAccount have differing case.

345.0.0

Added

  • [SQL] Added query support for generating new GUIDs. This can be used for randomly ordering the results of a query.
  • [WPF] Added calendar functionality. Constructing a CalendarController with a list of entry sources allows the control to be attached to a screen.
  • [ORM] New "Manual Calendar Entry" model feature which allows users to add custom entries into the calendar.
  • [ORM] QueryBatch.ToLookup that uses the passed in value as the key.

Changed

  • [ORM] IReminder.Type changed from type Type to IEntityInfo.

344.0.3

Fixed

  • [ORM] Trusted principals created by SecurityService now have permission for all flags.
  • [WPF] Accepting a user registration request with an existing username with a different casing would cause a new user account to be created with a duplicate username (but different casing).

344.0.2

Fixed

  • [WPF] ListController would leak memory under some circumstances through a task continuation awaiting SessionService.ShellExited.

344.0.1

Fixed

  • [WPF] CellReferenceControl would load its reference synchronously which was prone to causing deadlocks.

344.0.0

Changed

  • [ORM] 'Polite' bools, as seen in Instagile.WPF columns and criteria, are now the default - an attribute of type Boolean will print as "Yes" or "No".
  • [ORM] Non-null BLOB properties of length N now print as "N bytes" instead of "System.Byte[]".
  • [WPF] The way that List screens bind their cells to entity properties has been rewritten to fix a memory leak. The ListColumn property string DirectBinding, which described a WPF {Binding} path has been removed; columns now bind only to the entity itself, but may pluck out specific property values (or not) using the new property IValueConverter Converterand object ConverterParameter.

Added

  • [DOC] IDocumentAttribute.Value, which returns the FileDocument or ImageDocument as a DocumentBase.
  • [ORM] Typed ComponentService.GetSettingsAsync<T>() wrapper.
  • [WEB] <EnumStringField> component, which sets an IValue<string> to one of the names of its enum type parameter.
  • [WEB] <LogoutLink ForceReload>, which if set will cause the page to be reloaded after logout.
  • [WPF] Several specialised converters in The.WPF.Converters.Entities for use with custom ListColumns.

Fixed

  • [DOC] FilesystemDocumentStore had bit-rotted. It's fixed, brought under test and now properly supports thumbnails.
  • [WPF] InlineCollectionFieldBase not loading its values resulting in the text not being set.

343.0.0

Added

  • [ORM] RequestRegistrationImplementation which was previously internal. This class has a virtual method UserRegistrationRequestCreatedAsync which can be overridden to add application-specific behaviour when a new user registration request has been created.
  • [WPF] ComponentConfiguration.RegisteredUserAccountCreated which is invoked after a user registration request has been approved and a new user account created, but before the DisplayController showing the registration request is replaced by one showing the new user account.

Changed

  • [ORM] The response type of the RequestRegistration anonymous procedure is now Unit instead of bool.
  • [ORM] UserRegistrationOptions.EnrolmentUsername is now a property rather than a field.

Fixed

  • [MODEL] Generated report classes with a document attribute would produce compiler warnings due to a conversion from a non-nullable type to a nullable type.

342.0.0

Added

  • [VAL] Lens.Wrap(), which creates a Lens from another IValue.
  • [WEB] Collection criteria. These use a modal like in Instagile.WPF, and support arbitrarily nested subcriteria. They're integrated with query strings up to one level deep - unapplied sub-sub-criteria aren't saved in the URL (yet?).
  • [WEB] CommandContext.SetModal() and GetModal(), which allow scaffolded UI to loosely couple to modal registrations for the optional use of built-in or overridden commands. This may not be the ideal API long term.

Changed

  • [WEB] Moved many of the internals of to an inner namespace.
  • [WEB] The CollectionAddCommand used by will now use a modal to create the new entity (unless the command's overridden, or called from a context that doesn't supply a modal registration).
  • [ORM] Renamed AsEnumerable to ToList on QueryBatch.ResultGenerator, and AsEnumerableAsync to ToListAsync on QueryBatch.AsyncResultGenerator.

341.2.0

Added

  • [ORM] QueryBatch has new static methods for accessing its tree/path loading functionality without having to manually construct a QueryBatch in order to streamline cases where you only want to add one thing to the batch.

Fixed

  • [WEB] Collection & value-reference fields weren't filling the width of a section as they should. This looked particularly bad on mobile. (The actual API for this feature is to set a field's label to null, which DefaultEditSpec does for some relationships - but it was erroneously being normalised to a zero-length string label).

341.1.0

Added

  • [ORM] The.Export.RTF, a static class with helper methods for RTF generation.
  • [ORM] Report classes have special types for document attributes, which provide stringification of document metadata. For Images, this includes a function to create RTF picture objects. Example:
    @Model.Pic.RTF(100, null) // if you want your image to be 100 pixels wide
    
  • [WPF] ConfirmController, a modal controller that displays an application-supplied string to the user and presents a Yes or No choice.

Fixed

  • [WEB] Login failures can now be serialised correctly when using AJAX login (BackendAuthenticationStateProvider).

341.0.0

Security

  • [WPF] Updated ImageSharp to fix CVE-2025-27598, a denial-of-service vulnerability when loading maliciously crafted GIFs.

Changed

  • [ORM] DeploymentUtilities.DownloadFilesAsync is now ReconcileTargetDirectoryAsync. Callers should no longer delete the contents of targetDirectory before calling this method. The existingDirectory paremeter is now the existingDirectories parameter because it supports specifying multiple paths that could contain existing files to reduce the size of the download.

Fixed

  • [ORM] DeploymentUtilities.WaitForExitAsync failing to detect that a process has exited in rare cases.
  • [ORM] DeploymentUtilities.WaitForExitAsync lying in a debug log message that the process it is waiting for has exited, when it has not.
  • [SEC] PasswordAuthentication.ChangeCurrentUserPasswordAsync() was failing due to strict realm checks. (The checks are still strict, but it now uses the correct realm.)

340.0.0

Added

  • [SEC] SecurityService.LoginAsync() now returns Task<IPrincipal> containing the updated principal (the same one that's been set as CurrentPrincipal).
  • [WPF] New protected methods ValueChangedAffectingSteps and ValueChangedAffectingValidity on WizardBaseBase to reduce the fragility of its use of the weak event pattern.

Changed

  • [WEB] CredentialsAuthenticationStateProvider's LoginAsync(IServices, Credentials) has been replaced with a simpler method LoginAsync(Credentials) on a new type CredentialsAuthenticator. This wrapper type hides some implementation details and fixes many edge cases in web login scenarios.

Fixed

  • [WPF] Race condition in FastTabControl when a tab was already open on first Measure/Override. This resulted in "The.WPF.Shell.TDI.TabModel" text showing up when screens were opened from OnLogin.

339.0.0

Changed

  • [ORM] Rationalised the layers of batch-loading APIs we've accumulated over the years:
    • BatchBuilder is now OperationBatchBuilder. OperationBatchBuilder and OperationBatch are now internal. These types are part of the query-provider implementation.
    • ReifiedGraph is now ReifiedResult and its constructor is internal. This type is a low-level output of EntityFactory. Application code should generally use higher-level APIs from The.Entities, like QueryBatch or LoadGraphAsync().

Fixed

  • [RPC] LocalEndpoint now puts off an authorisation permissions lookup until the claimed identity is fully authenticated. This averts a hypothetical attack where a malicious caller could cause the application to run its authorisation code and, given an out of band oracle, learn some secret.
  • [WEB] On the server side, inside endpoints (when executing RPCs), the ClaimsAuthorisation default did not apply - unless you were using a custom IAuthorisation, there would be no roles. Instagile.Web instances now fall back to ClaimsAuthorisation if they don't have IAuthorisation or IEndpoint registered; if they have an endpoint, the assumption is that authz is delegated to an underlying backend.

338.3.0

Added

  • [WEB] <ListCollectionField> passes through extra attributes to its <EntityListView>.

Fixed

  • [WEB] <EntityListView AllowDirtyReads> didn't apply to preload includes.

338.2.4

Fixed

  • [WEB] It's no longer necessary to add ASP.NET Core services before AddTheFramework() - or at all, if you're only using it for API endpoints.
  • [WPF] The Reminders sidebar was trying to update in the background when not logged in - which would fail silently each time, wasting a bit of electricity.

338.2.3

Fixed

  • [WPF] RemindersController sometimes showing a global surface error on login due to accessing its Model property before it had been set.

338.2.2

Added

  • [WPF] DisplayController.GetIcons() for displaying tool-tipped images next to the screen title.

338.2.1

Fixed

  • [EXT] Instagile.vsix was broken due to a VsSDK update which packaged files a little differently.

338.2.0

Added

  • [WEB] TestSurface extension method to get the current model, typed.
  • [WEB] As a first step towards throttleable dev environments, latency can be simulated by setting Options.RPC.ServerLagEmulation to a non-null TimeSpan.

Changed

  • [ORM] EntityDocumentStore will now create and use a trusted principal for document access when running in an environment with a LocalRPCService. This allows applications using EntityDocumentStore to disallow user access to the StoredDocument entity.

338.1.0

Added

  • [WEB] IPageSpec.DefineModalEditLink, which lets you override the link used by <ListCollectionField> and other upcoming features.

Fixed

  • [ORM] When GetByID() is called for an entity that's already loaded in the context but with includeEtc: that aren't loaded, it will run the secondary queries instead of ignoring them.
  • [WEB] <ListCollectionField>'s modal presented <EntityEditViews> without calling LoadEntityAsync() from specs. This might not be the ideal way for things to work long-term, but to maintain backwards compatiblity with existing app code for now, it calls the spec method. This won't do any I/O if the entity is already loaded and it doesn't have any includes.
  • [WEB] Modal routing was buggy when performing an internal navigation from a url with a modal fragment to a url without one and then using the browser's Back button.
  • [WEB] SectionSpec.WithRow had an incorrect "label" parameter which overrode the whole section's label. This overload is now deprecated and the parameter is ignored.

338.0.1

Fixed

  • [WEB] Synchronous authorisation (the automatic kind done when the framework is initialised) assumed that all authorisers are authoritative, rather than checking first.

338.0.0

Added

  • [WEB] <ActionLink> and ActionLinkModel accept an optional href parameter. If set, the generated link will use the callback for standard navigations but have href set for auxiliary features.
  • [WEB] ModalRegistration.GetPath(route) returns the path that would be generated by Open(route).

Fixed

  • [WEB] <ListCollectionField> entity links now support middle- and right-click.
  • [WEB] <SidebarShell> would fail to display a page's titlebar if a modal was opened, the tab was hard-refreshed, and then the modal was closed.

Changed

  • [WEB] When using AddTheFramework() alongside ASP.NET Core subfeatures like MVC and Blazor, MVC's dependency registrations have to come first, so that the framework can integrate with it. This was already true for Blazor and raw middleware/kestrel code, but not strictly the case for backend apps - some features like AddControllers() or AddIdentity() could be specified after AddTheFramework() rather than before. Now the process is more strict, and AddTheFramework() will throw an error if you haven't registered some source of HTTP infrastructure first.

Removed

  • [BLD] Removed TeamCity build support and obsolete test dependencies.

Security

  • [SEC] Updated or removed all dependencies which had known vulnerabilities.

337.0.0

Added

  • [ORM] ModelID Guid property to IEntityInfo and AttributeInfo.
  • [ORM] ByID read-only dictionary property to EntityMetadataDictionary which allows looking up entity metadata by model ID.
  • [ORM] AttributesByID read-only dictionary property to IEntityInfo whic allows looking up attribute metadata by model ID.
  • [ORM] New "document security" feature which adds an authorisation layer to document operations.
    • Adds one entity to the model DocumentAccessEntry.
    • One DocumentAccessEntry represents one document access rule.
    • A document can have multiple access rules.
    • An access rule can grant access to a document either globally or through a particular entity.
    • If a document has no access rules, it is by default not accessible.
    • A principal that has access to a document can download it and its metadata, upload thumbnails, and create additional access rules for that document.
    • Users with the AccessAllDocuments flag or the admin permission can access all documents regardless of access rules or their level of access to particular entities or tenancies.
    • When accessing a document, the caller must provide a DocumentAccessAssertion to describe how they have access to it, which comes in two forms:
      • EntityDocumentAccessAssertion meaning that the caller asserts that an EntityDocumentAccessRule exists for that document and that the caller can access the entity described by the rule.
      • UnspecifiedDocumentAccessAssertion meaning that the caller has some implicit permission to access the document, such as via a GlobalDocumentAccessRule, DocumentOptions configuration, user flags or admin permission.
    • When uploading a document, the caller must provide a DocumentAccessRule describing a rule for accessing that document, which comes in three forms:
      • EntityDocumentAccessRule which refers to a particular entity and attribute by IDs, plus a NewEntity flag. Principals must provide a matching EntityDocumentAccessAssertion with the same IDs to be able to access a document using this rule, need to be able to read the entity described by the IDs, and the entity must exist for that principal.
        • If the NewEntity flag is specified it means that the document has been uploaded to be associated with a new entity that hasn't yet been saved. Document security allows some leeway for accessing a document uploaded in this way (a configurable period of 10 minutes by default and only from the uploading principal) before requiring that the entity exists.
      • GlobalDocumentAccessRule which allows anyone to access the document.
      • UnspecifiedDocumentAccessRule which means no rule should be added.
    • Document authorisation is handled by AuthorisingDocumentStore, a new IDocumentStore wrapper that is constructed automatically when composing the instagile framework.
    • When saving an entity, new access rules will first be created for any documents that may have been copied into that entity. If the context is not authorised to create those rules (due to not having access to the document it is attempting to copy) then the save will fail before any entity persistence operations are executed.
    • DocumentBase and its derived classes FileDocument and ImageDocument have a new DocumentAccessAssertion constructor parameter and property.
    • Root now includes a new MEDI service registration for AuthorisingDocumentStore if the document security feature has been enabled.
    • Added new options class DocumentOptions.
    • Added new job DocumentSecurityMigrationJob with associated options DocumentSecurityMigrationOptions.
      • By default this job will block startup and attempt to create an EntityDocumentAccessRule for every not null document attribute in every entity in the database, so long as no rules already exist.
      • If this migration would take too long, it can be configured to not block startup by disabling BlockStartupUntilComplete. Developers may also want to enable DocumentOptions.DefaultGlobalAccess so that users can access documents without an access rule while the job is running.
      • If the job is interrupted it will not be able to resume unless the option AbortIfAnyRulesExist is disabled. If this option is disabled, the job will run slower because it will need to check if particular rules exist before creating them.
  • [WPF] DocumentAccessRule property to ImageField and FileField which allows the access rule for newly uploaded documents to be inspected or modified.
  • [WEB] Added <OpenEntityLink>, used by <EntityListView> for its main column links. By default, it behaves like <EditPageLink>.
  • [WEB] <____Link> components' behaviour can be overridden by cascading a Func<IEntityInfo, LinkModel?> named for the tyope of the component. For example, <CascadingParameter Name="EditPageLink"> to override the generation of edit links within a tag hierarchy.
  • [WEB] <Page IsRoot>; true by default, can be set to false to indicate that some page-like ui is for a modal or a sub-region of the page. The value is passed through to <CommandContext IsRoot> and used by shells for presentation.
  • [WEB] New "routable modals" feature which lets webapps declare some UI to be presented modally by shells.
    • Modals are defined by <ModalRegistration Route="foo/{bar}" Title="Screen Title">. Their ChildContent receives values from the route template.
    • A modal can be triggered imperatively (use @ref to get access to the API) or by fragment routing (#foo/valueforbar).
    • Shells will present modals in a page-like fashion, hiding or disabling the base page.
    • Modals can be stacked, adding extra fragments to the URL and hiding/disabling previous modals.
    • Shells need to cascade an IModalContext to present modal stacks. The built-in <ResponsiveShell>, <SidebarShell> and <GridShell> have been updated accordingly.
  • [WEB] <ListCollectionField> uses a modal to allow editing unsaved entities and deep-linking to value children.

Changed

  • [ORM] IDocumentStore methods to include new parameters and added one new method.
    • DocumentAccessAssertion parameters describe how the caller is asserting that it can access a particular document.
    • DocumentAccessRule parameters describe a new access rule that the caller is attempting to create.
    • AddAccessRules is a new method that allows bulk creation of new document rules.
  • [ORM] RemoteDocumentStore procedures to account for IDocumentStore changes and the document security feature.
  • [SEC] PermissionSetBuilder methods to return this so as to enable fluent use of it within expressions.

Fixed

  • [ORM] query translation error when selecting values using !.
  • [WEB] DefaultCommandSpec's CollectionAddCommand could potentially do a sync read.

336.2.1

Fixed

  • [ORM] query translation error when selecting values using &, &&, | or ||.
  • [WEB] Startup would fail if a ScheduledJobBase job didn't have a configured schedule.

336.2.0

Added

  • [ORM] more RelationshipTree overrides for QueryBatch.
  • [WEB] IsReadOnly parameter to <EditPage> which makes all fields on the page read-only.

Changed

  • [ORM] QueryBatch will now ensure that all specified paths are loaded when starting from a partially loaded graph.

336.1.1

Added

  • [WPF] AllowCreateAccount option to IntegratedLoginOptions to determine whether administrators can create user accounts.

Fixed

  • [WPF] RemindersController would never recreate its CancellationTokenSource during relogin after cancelling it during logout.

336.1.0

Changed

  • [ORM] LoadGraphAsync will now verify that all specified relationships are loaded and will throw InvalidGraphException if a relationship fails to load.
  • [WPF] OnOpened and OnClosed are now sealed on ContentControllerBase, DisplayController, GridController and ListController. Applications should instead override OnControllerOpened or OnControllerClosed.
  • [WPF] ReferenceDataController.OnOpened is now sealed, applications should instead override OnControllerOpened.
  • [WPF] ContentControllerBase.OnOpened and OnClosed are now sealed. Applications should instead override OnControllerOpened or OnControllerClosed.
  • [WPF] Modified the SidebarControllerBase API, guaranteeing to sidebar implementations that they'll be presented for logged-in users (IsAuthenticated principals) only and do not have to deal with racy state. Most sidebars were already written as if this was the case, leading to subtle bugs.
    • Principal has been removed - it is safe to use Services.Security.CurrentPrincipal instead, as sidebars will only be attached while there is a login.
    • OnAdded() has been removed - put logic in CreateModel() instead (but note that it should not access base.Model).
    • OnRemoved has been replaced with DestroyModel(T model), which is passed the no-longer-valid model for cleanup. It should no longer be necessary to register and deregister sidebars using OnLogin/out delegates.

Fixed

  • [WPF] Reminders would open as editable even if the user didn't have write access to that entity.
  • [WPF] When using LoginScreen, OnLogout delegates wouldn't complete until a user logged back in.

336.0.0

Added

  • [ORM] IRelationshipTree interface which is implemented by both RelationshipTree implementations.
  • [ORM] overloads to graph loading methods on GraphNavigation that accept an IRelationshipTree. These versions are marginally faster because the tree has already been calculated, while the overloads accepting a RelationshipPath array must compute that tree.
  • [ORM] Prepend method to IRelationshipTree which creates a new tree with the current instance as its only child.
  • [ORM] new entity interface IEntity<T> which all entities now implement which allows for static generic access to its Metadata property without needing an EntityMetadataDictionary.
  • [ORM] overloads for graph loading methods on QueryBatch that accept an IRelationshipTree.
  • [ORM] PlaceholderEntity a class that implements IEntity<T> that can't itself be instantiated. Intended to be used with nameof when needing a concrete entity type to satisfy a generic type variable.

Fixed

  • [WPF] Requesting PKI registration would incorrectly use an empty string for a username when no username was specified.
  • [WPF] Automatic preference saving on logout (signing out without closing the application) was broken due to a latent bug in PreferenceService that was triggered by the CurrentPrincipal changes.

Changed

  • [ORM] Many types and methods previously requiring a type variable that must implement IEntity now require that variable to implements IEntity<T>.
  • [ORM] In general, applications having a type T where T : IEntity<T> can now replace metadata lookups of the form Entities.Metadata[typeof(T).Name] with T.Metadata and don't need to pass around metadata as much as before.
  • [WEB] DefaultEditSpec<T> no longer requires an EntityMetadataDictionary as a constructor parameter.
  • [WEB] Default specs, relationship fields, and some views that had an entity type variable T now require T to implement IEntity<T>.
  • [WPF] Most screen controllers, screen models, and relationship fields that had an entity type variable T now require T to implement IEntity<T>.

Removed

  • [WPF] Timer-based preference saving, which has been broken since 2018. Apparently nobody missed it.

335.1.0

Added

  • [WEB] option to enable or disable anonymous RPC endpoint mappings. Currently they are enabled by default. See EndpointOptions.IncludeAnonymousRPCRoutes.
  • [WPF] optional parameter to TestSurface.CancelModal and ConfirmModal (and equivalent methods on SurfaceExtensions) to ensure that a modal exists.
  • [WPF] CreateModal.ContentReady which when successfully completed indicates that the modal has finished loading.

Fixed

  • [WPF] CreateModalController never setting IsLoaded after an exception is thrown inside InitContentAsync.

Changed

  • [WPF] errors occurring during modal OnCompleted to be observable via the modal result.
  • [WPF] Rename ContentModel getSaveTask parameter to contentReadyTask which better describes its actual purpose.

335.0.0

Added

  • [WPF] Virtual method DisplayController.GetTextForTitle(), which allows overriding the dynamically-generated ScreenTitle for display screens.
  • [SEC] security "flags" which are named special permissions:
    • Having a flag should only ever increase a user's level of access or remove some kind of restriction.
    • Built-in flags go in WellKnownFlags. There's currently only one ScrambleData which replaces the admin flag checks in the data scrambling RPCs.
    • PermissionType has a new value Flag.
    • Added CheckFlag and AssertFlag to PrincipalExtensions.
    • Added PermissionSet.AllFlags to create a PermissionSet with all flags.
    • Added AllFlags and Flag to PermissionSetBuilder to add flags.
    • Added Permission.AllFlags.
    • Applications that grant the admin flag to some users will probably want to grant those users the either the AllFlags permission or WellKnownFlags.All so that they are automatically granted any new built-in framework flagss.
    • PermissionSet.AllExceptAdmin now also grants all flags.
  • [ORM] RelationshipTree a data structure representing a collection of RelationshipPath objects from a common root type that can be walked efficiently.
  • [ORM] RelationshipTree<TValue> which is very similar to RelationshipTree but allows a value to be attached to particular paths.
  • [WPF] optional CancellationToken parameter to AsyncScreenExtensions.LoadAsync.

Fixed

  • [ORM] EntityDocumentStore incorrectly reading from streams which could lead to the tail end of an uploaded document being replaced with zeros. This was particularly likely to manifest when using stream encryption due to quirks with .NET's CryptoStream.
  • [WEB] BlobDocumentStore throwing an exception when GetImageMetadata is called with the ID of a document without image metadata.
  • [WPF] DisplayController never setting IsLoaded after an exception is thrown inside LoadEntityAsync.

Changed

  • [ORM] IBulkDocumentStore methods to accept a CallbackEnvironment.
  • [WEB] BlobDocumentStore now implements IBulkDocumentStore except for GetBulkThumbnailData.
  • [SEC] PermissionSet constructor to include a new parameter flags for the new security flags feature.
  • [WPF] Saving a user account using a prebuilt WPF screen will now invalidate ALL role cache information, instead of just the roles for the account realm identity.
  • [WPF] Removed UI level read and write asserts from ScreenService.
  • [MDL] Renamed CollectionExtensions to GenericCollectionExtensions to avoid namespace clash with System.Collections.

334.0.0

Added

  • [RPC] GetCurrentUserPasswordHash to retrieve the cryptographic salt of the current user's password hash from their user claims.

Changed

  • [ORM] EntityMetadataDictionary is now an IReadOnlyDictionary instead of being a mutable Dictionary.
  • [RPC] ChangeCurrentUserPassword now returns a Unit instead of true.
  • [SEC] PasswordAuthentication.ChangeCurrentUserPasswordAsync no longer needs to read any account feature entities.
  • [SEC] IdentityAuthentication is now SemanticAuthentication and can be given a Semantics bitfield to restrict the allowed types of username.
  • [SEC] For authenticators that CanLookup, the subject passed to VerifyIdentityAsync() is now guaranteed to be an account username. Similarly, the Identities passed to CheckSignatureAsync() and EncryptDataAsync() are guaranteed to be in the Account realm - previously, such authenticators had to support either Realm.Account or Realm.Authenticated().
  • [WPF] ChangePasswordScreen to no longer require getCurrentUsernameAndHashAsync.

Fixed

  • [SEC] SemanticAuthentication can now handle inner authenticators with CanLookup=true.

Removed

  • [WPF] BuilderExtensions.GetCurrentUsernameAndHashAsync.

333.2.0

Added

  • [SEC] ReadOnlyAuthorisation which wraps another IAuthorisation and removes all write permissions.

Fixed

  • [RPC] GetIdentityRoles incorrectly comparing identities.

333.1.2

Fixed

  • [WEB] The fix for <CascadingUserAccount> was incomplete as it used 0-argument Clone(), which copies the principal.

333.1.1

Fixed

  • [WEB] <CascadingUserAccount> wasn't logging-in the user when using prerendering and a wrapping authenticator (like SharedSecretAuthentication). It would cascade a user account alrght, but one with an unauthenticated context - the entity data was persisted from the prerender, but security data was not.

333.1.0

Added

  • [SEC] RemoteAuthorisation which obtains a user's list of roles via an RPC and delegates to an inner IAuthorisation to determine the permissions for those roles.
  • [RPC] new built-in RPC GetIdentityRoles used by RemoteAuthorisation.

333.0.0

Added

  • [SEC] Improved OneTimeCodeAuthentication with bugfixes, new config options and a test suite.
  • [SEC] Added IdentityAuthentication, which wraps another authenticator to add ASP.NET Identity-compatible external claims - letting you log in with one or more of email address, phone number, etc.

Changed

  • [SEC] IAuthentication.CreateSignature is now async, in case of required lookups and because PKI signature is quite slow.

332.4.0

Added

  • [WEB] options to select which groups of framework routes should be mapped. The default is that all routes are mapped.

Fixed

  • [WEB] controller style RPC routes using UpdateControllerName instead of EndpointControllerName.

332.3.1

Added

  • [WPF] NRTs for ModalResult, allowing #nullable enable code to check IsCancelled in order to type-narrow .Result.

332.3.0

Added

  • [RPC] Builder.RemoveRPC() allows you to remove built-in procedure implementations; you can then replace them with your own if you like, or just leave them out to remove some functionality from an application.

Changed

  • [SEC] SecurityService.InvalidateAuthorisation will no longer invalidate role caches for other framework instances that share the same DI container. If you do need to do this, injecting IEnumerable<RoleCache> can achieve the same thing - that's what InvalidateRoleCacheJob now does.

Fixed

  • [SEC] OneTimeCodeAuthentication performing a case sensitive comparison against usernames when verifying identities.
  • [SEC] SecureStore allowing untrusted clients with a limited tenancy to access tenancies that they are not authorised to access by specifying that tenancy with their request.
  • [WEB] The role cache was not correctly applying across requests since v322, reducing performance of client-server applications.

332.2.0

Added

  • [SEC] OneTimeCodeAuthentication, which implements login by comparing a provided code to one generated earlier. At the moment it's mechanism-agnostic, supporting arbitrary usernames and leaving it up to the application how to translate those to message subjects (like email or SMS).

Fixed

  • [WEB] TimeBox was failing to parse 24 hour time.
  • [ORM] TransientEntityStore had an NRE when evaluating fused half-joins from a known entity produced no ID for that entity - a paradoxical situation which can be produced by tenancy restrictions.
  • [SQLITE] changes to an entity's PluralOverride not causing join tables and their columns to be renamed.

332.1.0

Added

  • [ORM] new overload of EntityQueryExtensions.Select for generically selecting an attribute via its metadata.

Changed

  • [ORM] Tenancy.ColumnName is now public so that applications can refer to the TenantID column by name without having to hardcode it.

332.0.2

Fixed

  • [SEC] RequireTenancySpecification wasn't available in web Options, which is its main use case.
  • [SEC] SecurityService is less noisy about failed logins; they're now considered Error instead of Critical, or Debug for structured failures of implicit login.

332.0.1

Fixed

  • [SEC] When using Server-Side Blazor, attempts to inject IServices that were outside an HTTP request or Razor component tree were failing; in practice, this afflicted Jobs.

332.0.0

Changed

  • [SEC] Login has been restructured. Previously, CreatePrincipalAsync() was necessary in the general case, but would cache authentication so that it could be reused by CreatePrincipal(), which was called by CreateContext(). The core layer now maintains a user session in the same way that the WPF layer used to do, with various consequences:
    • CurrentPrincipal, LoginAsync() and LogoutAsync() have moved from Instagile.WPF's SessionService to Instagile's SecurityService. CreateContext() uses CurrentPrincipal (as it already did in WPF).
    • CreateContext(IPrincipal) no longer allows for a null principal to be specified.
    • SecurityService's CreatePrincipal() and CreatePrincipalAsync() methods have been removed. They've been replaced with CreateLocalPrincipal() and CreateStandardPrincipalAsync(), but these have slightly different semantics; app should generally use CurrentPrincipal instead. The CreatePrincipal methods no longer do any interal caching (as CurrentPrincipal is itself a cache), and CreateLocalPrincipal() will no longer fall back to sync-over-async when async is required.
    • SetGlobalCredentials() and InvalidatePrincipal() have been removed; LoginAsync() and LogoutAsync() serve a similar purpose.
    • GetIdentityAsync() has been removed from IAuthentication - authenticators are always able to produce an identity or an error without doing any async work themselves.
    • GetIdentityRoles(), non-async, has been added to IAuthorisation. Like the non-async VerifyIdentity() method of IAuthentication, it's only available if IsAuthoritative (also added) is true.
    • When both authenticator and authorisor are authoritative, CurrentPrincipal will be logged-in at startup. Otherwise, you need to call LoginAsync() to log in. This is generally done using higher-layer infrastructure - LoginScreen in WPF, CredentialsAuthenticationStateProvider in Web.
    • Unit tests are likely to experience more disruption than application code, since each test tends to have its own framework instance and may need to log in. If you don't want to make a LoginAsync call in test fixtures, you can RegisterAuthorisation(new NoAuthorisation()), which will be able to log in automatically.
  • [WPF] The overload of ISubmenuBuilder.AddChangePasswordLink() which takes a bunch of delegates no longer also requires a PasswordAuthentication instance.

Added

  • [SEC] New framework option RequireTenancySpecification. If set, this enables the method SecurityService.SpecifyTenancy(), which can be called to set the requested tenant[s] to access; until it's invoked, a login session doesn't have any tenant access at all. The available tenants are an intersection of the ones you request and the the ones permitted by authorisation policy. The purpose of this feature is to allow applications to limit a session's access based on "top-down" information like a UI action or a URL route; some users (administrators, for example) may be permitted access to multiple tenancies but only on certain pages.

331.0.3

Added

  • [WPF] Caps lock warning on password login windows.
  • [EXTENSION] display of model node IDs and relationship side type to model editor.

Fixed

  • [WPF] Success and Information level surface notifications were being logged as error.

331.0.2

Fixed

  • [SEC] LocalEndpoint didn't work with AuthenticationProtocol.MatchingAmbientIdentities, erroneously producing a CredentialsMissing error even for authenticators that don't require credentials.
  • [WPF] type constraint on WizardBaseBase<T>.Bind<U> which made it impossible to avoid nullability warnings for nullable value types.
  • [WPF] wizards not being able to produce a null result.

331.0.1

Fixed

  • [BLD] Instagile.vsix packages are being uploaded to MyGet once again.
  • [ORM] Nullable annotations and possible null dereference in NullableBLOBSpecification.

331.0.0

Added

  • [WPF] IWizardHost.CalculateOnce(), which can be used to initialise for a ShowPage() call without re-run as the wizard progresses.
  • [WPF] Added more NRT annotations to Instagile.WPF.
  • [ORM] RequestReason and OtherUserInformation strings to IUserRegstrationRequest to store the reason the user needs access to an application and additional application specific information about the user and their application respectively.
  • [ORM] delegate GetOtherUserInformation which can be invoked by some login handlers and/or by the RequestRegistration procedure to attach some additional information to a registration request.
  • [ORM] new overloads for UserRegistration.RequestPkiRegistration and UserRegistration.RequestPasswordRegistration which accept more information about the registration request.
  • [ORM] IUserRegistrationRequest.ConfigureUserAccountAsync for non-interactive user account setup when a user registration request is being accepted.
  • [WPF] ScreenConfiguration.ComponentConfiguration which currently has one property ConfigureRegisteredAccount for interactive user account setup when a user registration request is being accepted.

Changed

  • [ORM] type of CalculationState.CutoffDate to DateTimeOffset and renamed it to CutoffInstant.
  • [ORM] a CacheByCountVisitor visitor type parameter from DateTime to DateTimeOffset.
  • [ORM] Changing an entity's ID after its attributes have been initialised will now throw an EntityIDChangedException. Please use SingletonEntityInitialiser if you need to create an entity with a known ID.
  • [MDL] User Registration model feature is now version 4.
  • [WPF] PasswordOnlyLoginHandler and PasswordLoginHandler to support GetOtherUserInformation.
  • [WPF] CreatePasswordOnlyAccountScreen to also ask for a reason for the user's registration request.
  • [ORM] Renamed UserRegistrationOptions.CustomUserAccountSetup to AutomaticallyAcceptedUserAccountSetup to better reflect what it actually does and added a CancellationToken parameter.

Removed

  • [ORM] support for conversion from DateTime to DateTimeOnly inside queries.

Fixed

  • [WEB] InstantField was not passing IsReadOnly through to its InstantBox.
  • [WPF] Only half the background of a pinned TabHeaderView was being filled when more than 1 row of tabs were open.
  • [WPF] CriteriaModalController was failing to open on search screens if user didn't have write access to the entity.
  • [WPF] password only registration confirmation message box being displayed behind the CreatePasswordOnlyAccountWindow.

330.2.1

Added

  • [ORM] IValue conversions for TimeOnly and Range<DateOnly>.

Fixed

  • [WPF] TimePicker control was trying to convert TimeSpan to TimeOnly.
  • [WPF] Improved TimePicker control, fixing binding errors and making the textbox take up the space it's given.
  • [WEB] DateOnly cells were incorrectly attempting to convert to DateTime.

330.2.0

Added

  • [BLD] NuGet packages are now available on Gitea as well as Gemfury.

330.1.1

Fixed

  • [WPF] DateOnly fields not being displayed.
  • [SQL] Returning calculated boolean values in SQL Server.
  • [SQL] DateOnly.FromDateTime truncation within subexpressions in SQLite.

330.1.0

Added

  • [ORM] extension method overload DateOnlyExtensions.ToDateTime which converts a DateOnly to a DateTime at midnight of the same date.
  • [ORM] support for DateOnly.ToDateTime and the zero and single parameter forms of DateOnly.FromDateTime.

Changed

  • [ORM] Improved cancellability of Recalculator.

330.0.0

Changed

  • [ORM] Time attributes are now represented in code as System.TimeOnly instead of System.TimeSpan. Date attributes are now System.DateOnly instead of System.DateTime with a zero time component. SQL schemas have not changed.
  • [MDL] Data scrambling feature v2, with an extra attribute on IScrambled for separate tracking of dates and datetimes.

329.5.0

Security

  • Updated SixLabors.ImageSharp to 2.1.9, fixing CVE-2024-41131 and CVE-2024-41132.

Added

  • [WPF] FieldHeader now displays text overflow ellipsis for long labels.
  • [WPF] All FieldControl will now display a tooltip of the field label when hovering over the label.
  • [WPF] Field tooltips now show the field label at the top of the tooltip.
  • [WEB] AdminMode on EditPage, DynamicEntityEditViews, EntityEditViews<T> and FieldContext which enables the display of AdminOnly flagged fields if the current user is an admin.
  • [WEB] new FieldSpec combinator overrides for VisibleIf, HiddenIf, ReadOnlyIf and ReadWriteIf which accept a FieldContext as a parameter.

Changed

  • [WPF] ExclusiveChoice and InclusiveChoice now contain a horizontal StackPanel of buttons rather than a UniformGrid, allowing labels to use more space.
  • [WEB] DefaultEditSpec to no longer filter out fields marked as AdminOnly. It now applies a visibility filter for such fields that will hide the field unless the FieldContext is not in AdminMode and the user does not have admin privileges.
  • [ORM] The Instagile, Instagile.Model.WPF and Instagile.Xunit packages are now fully <Nullable>enable</Nullable>.

Fixed

  • [ORM] GraphNavigation.LoadGraphAsync so that it works correctly with queries on interface types.
  • [ORM] EntityQueryExtensions.Select with RelationshipPath so that it works correctly with queries on interface types.

329.4.0

Added

  • [WPF] In SearchModal screens, when searching results in exactly one row, it will be automatically selected in the results.

v329.3.0 16 Jul. 2024

Added

  • [WPF] ListBehaviour<T> convenience subclass for concrete lists.
  • [WPF] ListBehaviour.InitialiseModel() for modifying or examining the list model.
  • [WPF] SearchOptions.ConfigureResults(), which lets you modify the contained result list's options.

Changed

  • [MGT] DependencyVersions.AppVersion and DependencyVersions.TheVersion are now required.

Fixed

  • [WPF] Modal search screens now select an entity when its hyperlink is clicked, rather than navigating to it in a new foreground tab.

v329.2.1, v329.2.2 15 Jul. 2024

Fixed

  • [WPF] Improvements to the new codesigning process.

v329.2.0 15 Jul. 2024

Added

Fixed

  • [WPF] It's now safe to override ScreenControllerBase's OnOpened() and OnClosed() in SearchController<T> subclasses without calling the base methods; SearchController uses multicast hooks so that it can't be broken by subclasses.
  • [WPF] Fixed global modals, which were broken when the global surface was made into a tab.

v329.1.0 08 Jul. 2024

Added

  • [ORM] QueryBatch.AddGraph overloads for partially loaded graphs.
  • [ORM] QueryBatch.AddReference and QueryBatch.AddCollection for loading relationships.

Fixed

  • [SQL] .Select()/.SelectMany() were not correctly applying tenant filtering.
  • [WPF] ISurface.ScreenDisposed was not triggering when TabbedShell.DestroySurface() was called.
  • [WPF] The create button was not working on LookupSectionedCollectionField due to its lens never having metadata.
  • [WPF] Errors opening pinned items will now display on the pin, rather than opening a tab in an error state.

v329.0.0 02 Jul. 2024

Added

  • [SEC] An overload of SecurityService.CreateTrustedPrincipal() that uses PermissionSetBuilder.
  • [WEB] FieldSpec.Hidden() and FieldSpec.Visible() (non-predicate versions).

Changed

  • [RPC] IEndpoint no longer takes an optional IServiceProvider to pass it around through the RPC infrastructure. RPCs, at the core runtime level, do not depend on DI.
  • [WEB] Combinator semantics:
    • VisibleIf() and .HiddenIf() can no longer make things hidden/visible, respectively - only visible/hidden.
    • If they return false, there will be no change to the original visibility.
    • ReadOnlyIf() now has a counterpart ReadWriteIf() and works the same way.
    • They all have non-If variants which unconditionally apply the desired status.

Fixed

  • [RPC] Procedures registered on a server using .AddRPC() can now be called from the server using RPCService.ExecuteAsync() - the proc will be registered in each local scope, with creation deferred until the composition root is available.

v328.0.0 28 Jun. 2024

Added

  • [WEB] CriterionSpec.ReadAccessRequired, a virtual property referencing the metadata of an entity type that the user needs read permission in order to see this column, or null.
  • [WEB] ColumnSpec.ReadAccessRequired, a property referencing the metadata of an entity type that the user needs read permission in order to see this column, or null.

Changed

  • [SEC] enforcement of query authorisation to require read permission to access any table or join table touched by the QIR in the query.

Fixed

  • [WEB] criteria, edit fields, and list columns being displayed for relationships that the user does not have access to dereference.
  • [WPF] criteria factories generating criteria for relationships that the user does not have access to dereference.
  • [WPF] list and grid controllers generating columns for relationships that the user does not have access to dereference.
  • [WPF] grid rows creating fields for relationships that the user does not have access to dereference.
  • [WPF] grid rows creating mutable fields for relationship properties where the user does not have access to write to the other side.

v327.0.0 24 Jun. 2024

Added

  • [ORM] QueryBatch.GetByIDOrDefault to match the previous behaviour of QueryBatch.GetByID.

Changed

  • [ORM] the return type of QueryBatch.GetByID, which will now fail if no entity of the given ID is found, matching the behaviour of other existing GetByID functions.

Fixed

  • [SQL] entity projections with limited tenancy access and no tenancies would sometimes produce invalid SQL when selecting an entity that has a relationship to a type with a tenant ID.
  • [SEC] the scoped context provided to IAuthorisation.GetIdentityRolesAsync did not have permission to access any tenant data.

Removed

  • [ORM] The.Attributes.Types and replaced its extension methods with implementations in AttributeSnapshot directly.

v326.2.0 19 Jun. 2024

Added

  • [SEC] CreateTrustedPrincipal() with no PermissionSet argument now includes all-tenant access.
  • [SEC] PermissionSet.Trusted, which grants the same permissions as a default call to CreateTrustedPrincipal().
  • [WEB] AddJob() overloads which accept a PermissionSet parameter to restrict the job's authorisation.

v326.1.0 17 Jun. 2024

Added

  • [WPF] In TabbedShell, as well as being a background when there are no tabs, the global surface can be an always-present main tab. This is configurable using ShellOptions.
  • [WPF] IScreenModel.HasTitleBar, which can be set to false to remove the header. This means no title and no command buttons.
  • [WPF] IScreenController.Pin(), which will display a screen on the root surface (aka a "pinned tab").

Fixed

  • [WPF] "The.WPF.Shell.TDI.TabModel" text showing up when screens were opened 'too fast'.
  • [WPF] FastTabControl styling issues.

v326.0.0 13 Jun. 2024

Added

  • [BLD] NRT annotations for namespaces The.(Import|Licensing|Logging|Persistence|Preferences|Security).
  • [PRF] PreferenceService.Unset(string key), which clears a single preference to its default value.
  • [SEC] AuthenticationResult.HasValue, an NRT-compatible property for checking whether Result or Error is populated.
  • [SQL] Query translation now supports [in]equality operators in .Select(). For example,
    Entity.Query().Select(e => e.X == 5)
    
    ...will produce a sequence of bools, true for entities where the X column is 5. !=, >, <, >= and <= are also supported.

Changed

  • [ORM] Breaking: Replaced Multigraph with QueryBatch which can handle more kinds of queries.
  • [ORM] Breaking: TranslationPolicy has a new property CurrencyManipulationUnsupported, currently only used by the SQLite implementation which does not support currency aggregates or arithmetic.
  • [ORM] Breaking: ComponentService now requires a ScramblingState.
  • [ORM] Breaking: ICustomScramblingBehaviour.PerformCustomScramblingBehaviour has a different second parameter (was a Random now is an IScrambler). You can still access a Random through IScrambler.Random.
  • [ORM] The data scrambler will now display an error if a user tries to scramble the same database more than once in the same operation.

Fixed

  • [MDL] Editor crash when creating a relationship in a section that is not the main section.
  • [MDL] Editor crash when creating a relationship where the main section does not exist on either side of the relationship.
  • [WEB] Data scrambling state not being persisted between RPCs making it impossible to monitor or cancel ongoing scrambling operations.
  • [ORM] Data scrambling throwing KeyNotFoundException when scrambling entities.

v325.2.0 21 May 2024

Added

  • [WEB] <BoxInput AutoFocus>, which causes the input to take focus when first rendered.

Fixed

  • [MDL] The AttributeType dropdown in the editor is now large enough that you don't have to scroll to see bool.

v325.1.0 20 May 2024

Added

  • [WEB] EntityState.TryRestore() and QueryState.TryRestore() now accept an optional context parameter, allowing you to control the context (and principal) used for deserialisation.

v325.0.0 20 May 2024

Added

  • [SEC] an overload of PermissionSet.Union which accepts more than two PermissionSets.

Changed

  • [ORM] The.Persistence.ColumnsByIndex and ColumnsByName are now structs. Each is a thin wrapper around a collection (array/dictionary respectively), so the actual column data is still stored on the heap.

Fixed

  • [ORM] Data import always running in unbatched mode (which is slower).
  • [WEB] Edit views no longer include AdminOnly fields by default.

v324.0.0 03 May 2024

Added

  • [RPC] The.RPC.Serialiser, a canonical and static type for serialising objects in the format used by The.RPC. As well as byte[] SerialiseObject(), it has a new method string PrintObject() which produces a human-readable form.
  • [SEC] New "tenancy" authorisation feature. Entities with a Guid TenantID attribute (name currently hardcoded) will be sharded based on the new PermissionType.Tenant permission. Principals without null or the relevant tenant id in their permissions will not be able to access rows that have the matching ID; they are filtered from all query results and relationship lookups.
  • [SEC] Overload SecurityService.CreateTrustedPrincipal(string name, PermissionSet permissions, params string[] roles), which lets you create a principal with any authorisation config you like rather than one that's "mostly trusted".

Changed

  • Updated from MessagePack.CSharp 2.3.75 to 2.5.140. This is a potentially breaking change for custom RPCs with message types in an inheritance hierarchy: the [IgnoreMember] attribute on a virtual property no longer applies to overridden properties of subclasses.
  • [WPF] SearchModalController has a new constructor argument for configuring its embedded SearchController. Applications overriding SearchModalController must add this new constructor parameter to continue being discovered by AutodiscoveryControllerFactory.

Fixed

  • [WPF] SearchModalController overrides not being autodiscovered.
  • [WPF] LookupInlineReferenceField opening a SearchModalController for reference data types that would allow the user to open and edit that reference data.

Removed

  • [RPC] SerializationFormat - we've settled on a binary serialisation format for performance. (For debugging, see the new PrintObject() method.)
  • [RPC] XmlSerializer, MsgPackSerializer and ISerializer. They were obsolete as well as misspelled.
  • [ORM] ExportProgress which was unused, this is technically a breaking change.

v323.0.1 23 Apr. 2024

Fixed

  • [SEC] incorrect case-sensitive username comparison in PasswordAuthentication, PrincipalIdentity and NTLMAuthentication.

Added

  • [ORM] disposal of encrypted session when a WPF client logs out.

v323.0.0 23 Apr. 2024

Changed

  • [MDL] New ModelFile version 12, in which a CreateRelationship event must be followed by two CreateRelationshipSide events. Saving an existing model file with the editor will update it to v12.

Fixed

  • [SEC] Logging in for a second time as the same user, when using a client-server setup and authz roles stored in the database, would fail to load roles the second time.
  • [SQL] When using ModelFile v12, adding new relationships is able to generate CREATE TABLE statements with their final table names, instead of a CREATE and then an ALTER. This makes it easier to add multiple relationships between the same pair of entities.

v322.1.1 19 Apr. 2024

Fixed

  • [WEB] named LocalEndpoints being constructed using the default endpoint's SessionCache, instead of their own SessionCache.

v322.1.0 18 Apr. 2024

Added

  • [WEB] a new overload for EndpointServiceCollectionExtensions.AddTheEndpointCore and EndpointServiceCollectionExtensions.AddTheNamedEndpointCore for endpoints that don't need RPCOptions.

Fixed

  • [WEB] incorrect text displayed sometimes in LookupCollectionField and CheckedComboBox.

v322.0.0 18 Apr. 2024

Security

  • Updated SixLabors.ImageSharp to 2.1.8, fixing CVE-2024-32036.

Added

  • [SEC] RPC InvalidateRoleCache as a standard RPC which can remotely invalidate the authorisation role cache.
  • [WEB] InvalidateRoleCacheJob which can be scheduled to invalidate the role cache.
  • [WPF] DisplayBehaviour.OnSavingAsync and DisplayBehaviour.OnSavedAsync.
  • [WPF] UserAccount DisplayControllers will now invalidate the modified user's cached roles when saving.
  • [WPF] Admin command to reset the authorisation role cache from UserAccount search screens.

Changed

  • [SEC] Most previous uses of RoleCache have been changed to instead use RoleCacheMap which maintains a separate RoleCache per IAuthorisation.
  • [SEC] SecurityService.InvalidateAuthorisationCache is now SecurityService.InvalidateAuthorisation and can be supplied with an Identity to invalidate the cached roles for only a particular identity.
  • [WEB] RPCEndpoints.ConnectAsync, RPCEndpoints.ExecuteAuthenticatedAsync and RPCEndpoints.ExecuteAnonymousAsync no longer have an instance parameter. That parameter exists on new variants of those methods with the prefix "Named".

Fixed

  • [WEB] EditField would ignore a FieldModel's ExtraParameters.
  • [WEB] Routing for named endpoints.

v321.1.0 03 Apr. 2024

Changed

  • [ORM] DateTimeOffset is now whitelisted in queries.
  • [SEC] SecurityService.InvalidatePrincipal will now also invalidate the principal's identity from the authorisation cache.

Fixed

  • [ORM] Fix PermissionSet.ReadExportAll not having read permissions.

Added

  • [WEB] EndpointOptions.RequireRPCAuthorisationPolicies for applying an application-specific authorisation policy against endpoint routes (except for the status route).
  • [WEB] EndpointServiceCollectionExtensions.AddTheEndpointCore and EndpointServiceCollectionExtensions.AddTheNamedEndpointCore to allow for applications to register custom endpoints.
  • [SEC] SecurityService.InvalidateAuthorisationCache to invalidate the authorisation cache.

v321.0.3 21 Mar. 2024

Fixed

  • [ORM] All entity queries implemented IOrderedEntityQuery, which made it difficult to check whether a given query had actually been ordered.
  • [WEB] <EntityBox> was not applying default sorting, which affected generated search criteria dropdowns.

v321.0.1 18 Mar. 2024

Added

  • [ORM] Internal method EntityKernel.DumpGraph() for debugging clones.

Fixed

  • [ORM] Recent changes to cloning, although they enabled new scenarios, caused a bug when entities with non-navigable references were cloned back after modal edit from the navigable side.

v321.0.0 12 Mar. 2024

Security

  • Updated SixLabors.ImageSharp to 2.1.7, fixing CVE-2024-27929.

Fixed

  • [WEB] Contexts returned by IsolatedSecurityService.CreateScopedContext did not implement IEntityContextAccessor which caused one-to-many references to not be linked up when their other side entity was loaded, and probably some other subtle issues.
  • [WEB] StartupJobBase will no longer create a JobRun entry until either the job completes, or it records its first progress so as to avoid executing writes while database migrations are still in progress.
  • [WPF] Prebuilt screens for model features now include relationship overrides again.
  • [WPF] Added fallbacks for GridController when preferences are in a bad state, so that trying to sort doesn't produce a "Sequence contains no elements" exception. It may still fail to actually sort.

Changed

  • [WEB] PeriodicJobBase now requires a StartupRequirements as a constructor parameter, and will wait for those startup requirements before its first job execution.

v320.3.0 05 Mar. 2024

Added

  • [WEB] StartupRequirements which provides a small abstraction for waiting for all registered IStartupRequirements.

Fixed

  • [WEB] RecalculationJob and RecalculationService will now wait for any registered IStartupRequirement before performing recalculation.

v320.2.0 27 Feb. 2024

Added

  • [SQL] LocalDatabase now supports using AttachDbFile in the connection string; it will still auto-create attached dbs, but will not delete them at cleanup.
  • [WEB] <AsyncPage>'s GetTitle parameter is now optional. It will fall back to LoadingTitle if that's set.

Fixed

  • [WEB] Persisting entity/query state through prerendering didn't work when InteractiveRenderMode was set.

v320.1.0 22 Feb. 2024

Added

  • [WEB] StartupRequirement is back in pogjob form. Rather than all StartupJobBases being requirements, only ones which also implement IStartupRequirement will be treated as such, and you can also register implementations that aren't a job at all.

v320.0.2 19 Feb. 2024

Added

  • [WEB] <StartupView> now displays error stack traces (if its ErrorContent is not overridden).
  • [WPF] While a screen command is executing, a wait cursor will be displayed. It can be suppressed with using var CursorOverride.NoWait();, and this is done automatically inside modals.

v320.0.1 16 Feb. 2024

Fixed

  • [WEB] Shell.RecalculationService wasn't handling shutdown correctly, causing framework webapps to wait for a timeout or hard kill.

v320.0.0 15 Feb. 2024

Added

  • [SCM] ScramblingOptions.RecalculateAfterScrambling flag.
  • [WEB] RPC endpoints will now wait for all StartupJobs, not just MigrationJob.

Changed

  • [SCM] Simplified scrambling config. Instead of providing several IServices, you set entitystores and it generates the necessary variants.
  • [WEB] AddTheLegacyFramework() has been replaced with AddTheNamedFramework(string name). It registers an IServices instance which can be looked up as a M.E.D.I. keyed service. Plugin registrations (IAuthentication, IDatabase, etc) will also be keyed.
  • [WEB] AddTheLegacyEndpoint() has been replaced with AddTheNamedEndpoint(string name). It creates an endpoint based on the corresponding named services, which MapTheFramework() will route to _the/rpc/{name}. (For example, _the/rpc/legacy if you want backwards compatibility.)

Removed

  • [WEB] ILegacyServices and ILegacyEndpoint marker types.
  • [WEB] StartupRequirement and AddStartupRequirement() - this was redundant with StartupJobBase now that jobs are available to client code.

Fixed

  • [ORM] If a non-empty entity collection was cloned, had elements removed but not added and then was cloned back, it would unnecessarily become unloaded, and then, if subequently re-loaded, be erroneously considered non-changed.
  • [WEB] AddTheFramework().Configure(o => o.SomeGroup.Value = x) was not modifying the SomeGroup of the underlying The.Composition.Root.

v319.0.3 13 Feb. 2024

Fixed

  • [ORM] Querying an entity's loaded collection's member's loaded reference's loaded collection would stack overflow, which - while arguably reasonable - was inconvenient.
  • [SQL] The QIR interpreter now implements 3VL for LEN() instead of throwing an exception when an argument is null.
  • [SQL] SQLEntityStore was failing to start up when more than one interface defined in a feature had a common superinterface (as is the case for ScramblingFeature).

v319.0.2 12 Feb. 2024

Fixed

  • [WEB] AddTheLegacyEndpoint() was using nonlegacy services.

v319.0.1 12 Feb. 2024

Fixed

  • [ORM] Fixed an exception when using EmptyQuery as a frozen query (which is done by WPF List screens).

v319.0.0 07 Feb. 2024

Added

  • [ORM] IEntityQuery.ToHashSet[Async]().
  • [???] Quasiquote criteriatree predicated-aggregate subspecification projections.

Changed

  • [ORM] IFrozenQueryable is now IFrozenQuery; it and IEntitySet inherit from IEntityQuery instead of IQueryable.
  • [ORM] IEntitySet.AsLoaded() returns an ILoadedSet instead of just an IEnumerable. It still has the same semantics, throwing if the set is not actually loaded.
  • [ORM] EmptyQuery now requires a context, but no longer has edge cases where it doesn't function properly.

Removed

  • [ORM] - IEntityQuery.SelectMany() no longer accepts arbitrary IEnumerables, only IEntitySets - such queries would not have produced valid SQL.

v318.0.5 06 Feb. 2024

Fixed

  • [ORM] If an entity collection which had been unloaded by a clone was re-loaded twice concurrently (due, perhaps, to slow reactive handlers running on the dispatcher), it would incorrectly re-load with the pre-clone state.

v318.0.4 01 Feb. 2024

Fixed

  • [LOG] Improved handling of edge cases around cancellation, manual jobs and failed timed operations.

v318.0.3 31 Jan. 2024

Added

  • [ORM] Queries that invoke a static Equals method, such as string.Equals or object.Equals are now supported. This uses the implementation of the persistence back-end to perform the comparison, and ignores any additional parameters such as a StringComparison enum value, so the behaviour of the query in memory may differ.

Fixed

  • [ORM] Fix ClaimsAuthorisation.IsAdminAsync throwing an exception when the user's claims are not loaded.
  • [RPC] Licensing was being initialised per-instance, which is very slow when you have many framework instances in a server.
  • [WPF] Fix ValueTranslator error appearing sometimes when opening a UserAccount display screen.
  • [WPF] Fix RecentItemsController failing to refresh its pins upon loading.
  • [WPF] Fix several potential and actual null dereferences in RecentItemsController.

v318.0.2 31 Jan. 2024

Added

  • [LOG] Timed operations like RPCs and SQL queries, which log their details if they run too long, will also log the operation details if it fails (throws an exception).
  • [SQL] Improved error handling for deserialisation failures.

Fixed

  • [SQL] OrderBy(entity reference property) was generating unserialisable QIR.

v318.0.1 30 Jan 2024

Changed

  • [SEC] Options.DisableAuthorisationCache has been replaced with the ability to register a RoleCache which may be shared or null.

Fixed

  • [SQL] DML emit could produce the incorrect "IN (NULL)" for empty collection element checks. It generates "1=0" now, and these checks are optimised away before reaching emit anyway.
  • [WEB] Now that The.Web.IServices is scoped, authorisation checks were being performed on every RPC call. AddTheFramework() uses a shared cache to prevent this.

v318.0.0 29 Jan. 2024

Added

  • [WPF] SuggestionField now supports async suggestions, via constructor overloads which take Func<Task<IEnumerable<string>>>/IEntityQuery<string>/IEntityQuery<IEntity> (which selects the entity's .Text).

Changed

  • [ORM] TransientEntityStore has been reimplemented as an SQL AST interpreter, instead of a converter from IQueryable to IEnumerable. This has a number of benefits:
    • Performance is improved.
    • No generated code required.
    • Semantics are more similar to RDBMS entitystores.
    • We're decoupled from LINQ and free to experiment with alternatives.
  • [ORM] Query-based ReadOperations now include a SQL AST instead of LINQ expressions. The AST is directly serialisable, removing the need to convert to and from expression "surrogates". Performance and edge-case support should both be improved.
  • [WPF] SuggestionField's filterSuggestions parameter has been replaced with overloads which perform the filtering themselves (for example, Func<string?, IEntityQuery<string>>). This allows consumers to implement filtering efficiently with SQL, or choose not to perform filtering at all.

Removed

  • [MODEL] <GenerateProxies> is no longer required.
  • [ORM] The.Linq.Surrogates has been deleted; we are no longer in the business of serialising the unserialisable.

Fixed

  • [SQL] Queries with multiple sequential Concat() calls had incorrectly ordered results.
  • [SQL] Queries with unnecessary .Distinct() followed by Select()ing a non-entity value would erroneously make the value DISTINCT.
  • [SQL] ElementAt[OrDefault]() was incorrectly translated.
  • [SQL] SQLiteEntityStore couldn't read/write IsLegacy attributes, even in legacy mode.
  • [SQL] Reifying entities no longer requires a hashmap lookup for each property.
  • [IMPORT] ImportData() was failing to copy data into entities with multiple transient attributes.

v317.4.1 22 Jan. 2024

Fixed

  • [WEB] Fixed AuthorizedMenuModel not having a default (null) for Roles.

v317.4.0 22 Jan. 2024

Added

  • [WEB] AuthorizedLinkModel and AuthorizedMenuModel now support Roles as well as (or instead of) Policy.

v317.3.0 19 Jan. 2024

Added

  • [WEB] New option for AddTheFramework(): InteractiveRenderMode, which can be set at startup to choose what kind of interactivity framework components will use. By default it's InteractiveServer, which we use in most apps.

Fixed

  • [WEB] <JobControlView> was showing "Binding not set" for jobs that don't report any progress.
  • [WEB] Built-in pages apply AuthorizationOptions.DefaultPolicy (if there is one).
  • [WEB] Built-in pages have a @rendermode so that they can be used as interactive islands within a static shell.

v317.2.2 18 Jan 2024

Fixed

  • [WEB] <FrontlineTheme> now defines font sizes in non-font-specific terms so that the size variables can be used for things like icons. (The default theme already did this.)

v317.2.1 18 Jan 2024

Security

  • Updated System.Data.SqlClient to 4.8.6, fixing CVE-2024-0056.

v317.2.0 17 Jan 2024

Added

  • [WPF] Added tabstops to command buttons within screens.

Changed

  • [DOC] WriteOneReadManyDocumentStore and WriteOneReadManyBulkDocumentStore now use CallbackEnvironment for logging instead of an ILogger constructor parameter.

v317.1.0 15 Jan 2024

Added

  • [WPF] OptionalExternalInstall method for UpdateOptions. This method will use a pipe to Tortosa if it is installed, falling back to launch-and-copy otherwise.

v317.0.0 13 Jan 2024

Added

  • [WEB] <FeatherIcon> control, which displays SVG icons with consistent styling. Icons are from the free https://feathericons.com/ set - hence the name.
  • [WEB] IsPrimary flag for <ActionButton> and Command. Primary commands will be rendered as primary buttons, which have an emphasised appearance.
  • [WEB] <ActionButton Level>, an optional parameter to apply colour schemes.
  • [WEB] <FileButton>now uses <ActionButton> internally and supports the same styling parameters.

Changed

  • [???] The.Logging.NotificationSeverity is now The.MessageLevel.

    This type has moved around a few times.. it originally described notifications in WPF, but is used for both notifications and datastate in Web. It doesn't fit in logging, though, because it has nothing to do with log levels! Since we don't have a general The.Shell (yet?), to the root namespace it goes.

  • [WEB] Replaced IWidget.IsInvalid with Validity, an optional MessageLevel which allows edit widgets to indicate any data state.

  • [WEB] Replaced <FieldLabel HelpText> with Messages, a list of icon+level+text structures.

  • [WEB] <NotificationView Severity> is now Level.

  • [WPF] NotificationModel.Severity is now Level.

Removed

  • [WEB] The.Web.Controls.Icons are gone - use <FeatherIcon> instead. Our previous hardcoded icons had an OnClick parameter, which inadequately duplicated some of the functionality of links; the new component is designed to be used inside a link or button and will be styled appropriately.
  • [WEB] Non-generic FieldSpec has been made abstract, and fieldspecs can no longer be created from a bare renderfragment instead of a typed component. Nobody was using this, and many features assume a <FieldBase>-inheriting component.
  • [WEB] <FieldValidationContainer> has been deleted. Field warnings/errors are now displayed using an icon in the label. (You can add a callback to <FieldBase OnValidationResultsChanged> to do it some other way.)

v316.1.5 09 Jan 2024

Fixed

  • [RPC] Slow-RPC detection was dumping the entire serialised request to logs at warning level. Changed to just be the procedure name.

v316.1.4 05 Jan 2024

Added

  • [WEB] <ColumnsPanel MinRows>, an optional parameter to force a minimum height when there's a lot of horizontal space.
  • [WEB] Documentation for some of the core types in The.Web.Entities.

Fixed

  • [WEB] <SidebarShell> had a broken default logo (it was still pointing to Instagile.Web.Frontend instead of Instagile.Web.Client).
  • [WEB] <EntityCriteriaView> would get cut off in Chrome when using a 4k screen and only two criteria.

v316.1.3 04 Jan 2024

Fixed

  • [WEB] <CreatePage> was limited to a single column due to incorrect nesting of panels.

v316.1.2 22 Dec 2023

Fixed

  • [WEB] Instagile.Web.Client.nupkg contained some stray package.json files from dependencies. Harmless, but annoying.

v316.1.1 21 Dec 2023

Fixed

  • [WEB] Under .NET 8, authorisation was failing when using both integrated (IIS) authentication and a Blazor website.

v316.1.0

Added

  • [ORM] Synchronized<T>, a mutex-like type which protects data behind a disposable guard object. The guard can be passed around to control ownership of the protected resources.
  • [SEC] IAlgorithmProvider, an abstraction over platform-specific cryptographic primitives. Supports BCL crypto as well as WebAssembly.
  • [WEB] AddTheEndpoint() now implies AddHttpContextAccessor() (which is required for most endpoints).
  • [WPF] ListController now exposes its set factory to subclasses which will prevent a warning when using a primary constructor and making use of the set factory in a subclass.

Changed

  • [SEC] IAuthentication's EncryptData() method is now EncryptDataAsync(). Both DecryptDataAsync() and EncryptDataAsync() receive an IAlgorithmProvider.
  • [RPC] The.RPC.ISerializer.DeserializeObject is now TryDeserializeObejct.

Fixed

  • [ORM] More NRTs.
  • [RPC] Race condition in RPCClient when session encryption took a long time - session renewal could tear down resources while they were still being used by ongoing work.
  • [WEB] <EntityCriteriaView> had unnecessarily janky loading, including a sync wait on async criteria.
  • [WEB] Fixed various small edge cases that didn't work well in WebAssembly.

v316.0.1

Fixed

  • [ORM] PartialEvaluator now understands the short circuiting behaviour of AndAlso and OrElse binary expressions and will not attempt to locally evaluate the right hand side if the left hand side is locally evaluatable and would trigger short circuiting behaviour.
  • [SEC] Removed client-side authentication rate-limiting. When you had a server-side authentication error, the rate limit would frequently trigger due to retries, concealing the actual problem.
  • [WEB] AddTheFramework() was missing the ASP.NET Core logging integration that its previous incarnation had.
  • [WEB] <DataFixControlView> no longer throws when you don't have an SQL entitystore registered. (It won't do anything useful, but it won't throw.)

v316.0.0

Changed

  • [WEB] The.Blazor namespace has been merged into The.Web. The.Blazor.Controls is now The.Web.Controls, etc. Overlapping components have been combined, using the api from The.Blazor and the features of both.
  • [WEB] MapTheFramework() includes routes based on which services are registered; previously, AddTheFramework() implicitly called AddTheUpdates() and AddTheEndpoint(). Client updates and RPC endpoints are now opt-in.
  • [WEB] The AddThe___() prefix is now reserved for framework services; adding app components doesn't use a prefix. Specifically:
    • AddTheRPC() is now AddRPC().
    • AddTheReminders() is now AddReminders().
    • AddTheOverrides() is now AddSpecs(), and it isn't needed in most cases - override specs from the assembly calling AddTheFramework() will be discovered automatically.
    • AddJob(), AddStartupRequirement() and AddDataFix() were already unprefixed.
  • [WEB] Structured pages have turned out to be a key primitive. Accordingly:
    • Namespace The.Web.Pages (a.k.a. The.Blazor.Pages; see above) is now The.Web.Entities.Pages.
    • Namespace The.Web.Commands is now The.Web.Pages.
    • <CommandedPage> is now just <Page> (and <LoadingCommandedPage> is <LoadingPage>, etc).

Removed

  • AddTheScopedFramework() - combined with AddTheFramework(). Overloads of AddTheScopedFramework() that were previously deprecated have been removed.
  • The.Blazor.IServices - combined with The.Web.IServices.
  • The.Blazor.IEntityContext - combined with The.Web.IEntityContext.

Fixed

  • [WEB] Improved composition performance - it's now cheap to create a large number of framework instances.
  • [WEB] Eliminated dependencies, making the closure of Instagile.Web.Client.nupkg smaller.

v315.0.0

Added

  • [RPC] RPCOptions.ServerAnonymousRateLimit config option.
  • [TEST] TestOutputLoggerProvider can produce ILogger<T>.
  • [TEST] Extension methods on ITestOutputHelper to create loggers.
  • [WEB] The.Blazor.IServices supports more authentication scenarios. In particular, it's now possible to use it with backend authentication (deriving from HttpContext) and to register custom authentication when not using DI.
  • [WEB] MapTheFramework() includes the functions of EndpointControllerBase.
  • [WEB] MapTheFramework() includes the functions of AccountControllerBase.
  • [WEB] Made <ResponsiveShell> easier to style by keeping the __chrome class unconditional.
  • [WEB] Improved responsiveness of <BarTable>, <EntityListView> and <EntitySearchView>.
  • [WEB] <Spinner>, a simple animated circle.
  • [WEB] ISelectionWidget<T>, a common interface for widgets that let you pick from a list.
  • [WEB] <ListBox> implements ISelectionWidget and has been extended with an option-content property.
  • [WEB] <RadioGroup> implements ISelectionWidget and supports arbitrary T (previously just string).
  • [WPF] IntegratedLoginOptions.MenuGroupName, which controls where account-related commands get put.
  • [WPF] ShellOptions.ConfigureModel, a delegate for customising the UI.

Changed

  • [RPC] Renamed some RPCOptions members to make their purpose clearer.
  • [RPC] WebEndpoint uses the new endpoint update route by default.
  • [WEB] The four web packages have been merged into two:
    • Instagile.Web, the top-level library with all features
    • Instagile.Web.Client, a subset containing only non-backend code Most applications will use Instagile.Web.nupkg. To minimise the breaking change, namespaces have been left alone. They'll be renamed for consistency in a future release.
  • [WEB] Applications which reference static files from _content/Instagile.Web.Frontend must change to _content/Instagile.Web.Client.

Deprecated

  • [WEB] EndpointControllerBase, which is redundant when using MapTheFramework().
  • [WEB] AccountControllerBase, which is redundant when using MapTheFramework().

Removed

  • [ALL] Support for .NET 6 and 7, except in Instagile.Model.
  • [MODEL] Instagile.Model.Web.nupkg (it's now part of Instagile.Web.Client).
  • [WEB] Instagile.Web.Backend.nupkg (it's now part of Instagile.Web).

v314.3.5 (backported from v320.0.0)

Fixed

  • [ORM] If a non-empty entity collection was cloned, had elements removed but not added and then was cloned back, it would unnecessarily become unloaded, and then, if subequently re-loaded, be erroneously considered non-changed.

v314.3.4 (backported from v318.0.5)

Fixed

  • [ORM] If an entity collection which had been unloaded by a clone was re-loaded twice concurrently (due, perhaps, to slow reactive handlers running on the dispatcher), it would incorrectly re-load with the pre-clone state.

v314.3.3

Fixed

  • [ORM] Cloning collections with removed elements into a context containing the same collection without removed elements left the collection in a state which, if neither empty nor subsequently fully loaded, would return query results from the datastore without taking in-memory state into account.

v314.3.2

Fixed

  • [WEB] Obfuscation broke the autoupdate API.

v314.3.1

Fixed

  • [WEB] Deployment.Version property had been renamed by accident!

v314.3.0

Added

  • [WEB] MapTheFramework() now includes the functions of UpdateControllerBase. For backwards compatibility, it will create both the old and new routes unless this is disabled by calling MapTheFramework(options => options.IncludeControllerStyleRoutes = false).
  • [WEB] IUpdateService and things that depend on it no longer require a controller name. If no controller name is set, it will use the new mapped routes.
  • [WPF] AutoUpdater uses the new update route by default, but will fall back to the old one for backwards compatibility.

Changed

  • [WEB] Unsplit DeploymentVersions.AppVersion.

Deprecated

  • [WEB] UpdateControllerBase, which is redundant when using MapTheFramework().

v314.2.4

Fixed

  • [WEB] <EntityEditViews> didn't actually have the change supposedly made in v313.0.0.

v314.2.3

Fixed

  • [WEB] Fixed LookupCollectionField not rerendering after completing loading.

v314.2.2

Fixed

  • [WEB] More bugs in DeploymentVersions.Create().

v314.2.1

Fixed

  • [WEB] DeploymentVersions.NetVersion now returns the target version of .NET instead of the current runtime.

v314.2.0

Added

  • [WEB] DeploymentVersions.AppVersion split into ServerVersion and ClientVersion, which contains a Deployment.

v314.1.1

Fixed

  • [WPF] Race condition in DisplayController - placeholder content could overwrite the real screen due to a missing lock.

v314.1.0

Added

  • [WEB] MapTheFramework(), a new extension method to provide built-in HTTP apis for internal framework use.

    Initially, this provides a pollable version endpoint which can be used by Echidna for apps that don't have a downloadable client.

v314.0.1

Fixed

  • [DOCUMENTS] Images with EXIF orientation metadata would not display correctly in some circumstances.

v314.0.0

Added

  • [WEB] New namespace The.Blazor.Routing for the rapidly-proliferating ____LinkModel and ____MenuModel classes.
  • [WEB] LinkModel.Activate() for programmatic use. Many subclasses are RoutableLinkModels which only require a navigation manager; others require arbitrary DI services.
  • [WEB] IPageSpecs can now produce any kind of RoutableLinkModel instead of just NavLinkModel.
  • [WEB] ClientLinkModel (replacing PageService.GetClientDownloadLink()).

Changed

  • [WEB] Moved PageService, IPageSpec and LinkContext to The.Blazor.Routing.

Removed

  • [WEB] PageService.GetClientDownloadLink() (replaced by ClientLinkModel).

Fixed

  • [WEB] Separated config/commands callbacks on IPageContext - the page config is available earlier, so this smooths initial rendering without losing the commands. Which we did in fact lose, back in 312.0.0.

v313.1.2

Fixed

  • [WEB] <LinkReferenceField> passed a misspelled parameter to another component and exploded.

v313.1.1

Fixed

  • [WEB] We were calculating sidebar widths by rounding to a multiple of --the-unit, but this does not work in Chrome yet. For now, ResponsiveShell's sidebar is fixed width but can be overridden like so:
    #the-responsive-shell {
        --the-sidebar-width: /* approximately 200px */;
    }
    

v313.1.0

Added

  • [WEB] <ListBox> now supports splatting onto the underlying <select>.
  • [WEB] <ProgressBar> can now have direct content instead of a text label, and its styling has been revamped.

Removed

  • [WEB] <Tooltip Theme> - no apps used it, and it was exposing an implementation detail of tippy.js. Tooltips can now be themed using the same variables and classes as other controls.

Fixed

  • [WEB] It's now clearer when links are disabled, particularly <ActionLink> links.
  • [WEB] <CalculationControlView> is useful but looked kind of awful. It has become less-awful. (Specifically, it's always a bar rather than some arbitrary quantity of paragraphs).

v313.0.0

Added

  • [WEB] <SectionField> now supports LoadingContent for deeper placeholders.
  • [WEB] The Attach(Top|Right|Bottom|Left) flags which were present on some Box controls are now available on all of them.
  • [WEB] <ComboReferenceField> and <ListReferenceField> now display a link when IsReadOnly (unless they're modelling reference data).
  • [WEB] More <ResponsiveShell> config options.

Changed

  • [WEB] Some namespaces have been reorganised. The.Blazor.Cells and The.Blazor.Fields have been moved under The.Blazor.Entities, and The.Blazor.Controls.Primitives has been added. This new namespace will contain components which are building blocks for controls but not useful on their own, like the ___Chrome types.
  • [WEB] CancellableLoaderBase is now CancellableComponentBase.
  • [WEB] <EntityEditView> is now <EntityEditViews>, plural; it no longer contains internal panels. Instead, it creates multiple blocks of content which can be composed or laid out by the consumer. This markup:
    <DynamicEntityEditView Entity="@context" />
    
    ...would now be written like this:
    <ScrollPanel Horizontal="OverflowMode.Hidden">
       <ColumnsPanel>
           <DynamicEntityEditViews Entity="@context" />
       </ColumnsPanel>
    </ScrollPanel>
    
    <EditPage> does this by default, so scaffolded UI hasn't changed.

Fixed

  • [WEB] <BoxButton> is now smarter about its borders in various edge cases.
  • [WEB] Shell text is now more responsive to root font-size - --the-fs-etc have been redefined in rem.

v312.0.0

Added

  • [WEB] <EcoTheme>, a simple reskin which exists to demonstrate how to write themes. It may also be useful for test environments.
  • [WEB] <AsyncCommandedPage LoadingTitle>, an optional parameter to set the page's perhaps-temporary title before it finishes awaiting.

Changed

  • [WEB] Rewrote the CSS variable system used for theming, now that we have a better idea of Instagile.Web's requirements. Details follow, but the full API can be found in Styles*.css.

    The ad-hoc colour palette has been replaced with a set of named hues, defined as colour ramps; this increases variety and allows consistent styling across shells and apps. The main hues are "neutral", for data entry; "chrome", for shell/page decorations; and "action", for widgets and links. For example, shells generally use --the-hue-neutral-1 (the second-lightest neutral colour) for the background of pages, but they might use neutral-0 or -2 for an area intened to stand out. See theme.css for details.

    Metrics variables --the-unit-1x/2x/etc have been halved and the linear progression has been made geometric. We use what were formerly half-units a lot, so it's desirable to keep these on an integer multiple. For special cases, --the-unit gets multiplied as necessary, but there are also named multiples like --the-unit-fullrow. These semantic lengths can be separately overridden to decouple things like row height from the overall design system.

  • [WEB] Themes and shells are now fully decoupled. <SidebarShell> no longer includes <FrontlineTheme>; instead, any shell can be used with any theme. The default is called "Inky" after our main desktop app theme, which it resembles, but this name is hypothetical - there's no actual InkyTheme component.

Fixed

  • [SEC] Trusted principals now have the admin bit (but not the admin role).
  • [WEB] Design improvements to <GridShell> and <ResponsiveShell>.
  • [WEB] <CommandedPage> and friends have optimised title-setting performance. This sounds silly but it prevents a FOUC when switching pages.
  • [WEB] Positioning of the tick in IsSmall checkboxes.
  • [WPF] ListColumn.UniqueKey (rather than Caption) is now used more consistently to identify columns when communicating between the model and view.

v311.2.2

Fixed

  • [MODEL] SemVer.CompareVersions, our extended-semver implementation that also works with four-number Microsoft versions, did not support prereleases with hyphens inside the prerelease part of the version. This prevented loading the extension on computers with a prerelease version of .NET Core 3 installed.

v311.2.1

Fixed

  • [WEB] CSS bundle ordering issues.

v311.2.0

Added

  • The framework now supports (but does not require) .NET 8. Building requires the .NET 8 SDK, which comes with Visual Studio 2022 17.8. Tests all run on .NET 8.
  • [EXTENSION] The extension no longer specifically requires the .NET 5 WindowsDesktop runtime - any version >`= 5 will do.
  • [SEC] PermissionSet.AllExceptAdmin, which is currently equivalent to ReadWriteExportAll and intended to be updated with any new types of permissions that we might add later.
  • [WEB] <SidebarShell>'s footer can be customised with the FooterText parameter.

Fixed

  • [EXTENSION] Crash when loading editor config from the solution's references fails - this is now handled in the same way as errors from the editor itself.
  • [SEC] Trusted principals did not have permission to export data.

v311.1.0

Added

  • [SEC] FailureCode.VerificationOneTimeCodeAttemptLimitExceeded.
  • [SEC] Unsuccessful authentication is now rate-limited more generally - if you've failed to log in repeatedly as a particular asserted identity, it will return FailureCode.RateLimitExceeded for attempts faster than 3 per 10 seconds. Successful authentication resets the limit.

Fixed

  • [ORM] WellKnownProcedures was not aware of ReminderUpdateQuery.
  • [ORM] entity.Collection.ToEntityQuery().SomeOperator() didn't work properly - there were major interop edge cases. This could cause failures when collections were used as the choices to restrict reference pickers in WPF.
  • [SEC] NoAuthorisation would not allow users to export data.
  • [WEB] <SidebarShell>'s sidebar now covers the whole height of the screen even if your browser window is a funny size relative to the menu length and page length.

v311.0.0

Added

  • [SEC] Two new authentication FailureCodes: VerificationExpiredCredentials and AccountRequiredClaimInvalid.
  • [WEB] <CheckedListView>, a list view that allows selecting of entity rows.
  • [WEB] Further improved <ResponsiveShell> design.

Changed

  • [SQL] DDL.GetColumnDefinition has a new parameter.
  • [WEB] <MenuView> has been extracted from <SidebarShell> for build-your-own-shell purposes. Existing users of <SidebarShell> will need to stick a menuview in there if they still want one. It has a weird parameter, string? ConsumeMargin; if set, this will cause the menu to "eat" space around it, realigning its links and padding to cover a larger area. This is intended for use inside padded regions.
  • [WEB] Similarly, <NavBar> is now <MenuBar>. Both components are named this way to indicate that they're designed to contain links (directly, or via a <BoundMenu>).
  • [WEB] CombinedMenuModel constructor no longer requires IServices.

Removed

  • [WEB] <CascadingSelectionContext>. Use <CheckedListView> instead.

Fixed

  • [MODEL] Source generated templates would sometimes produce incorrect property indices, particularly the solution contained multiple models.
  • [MODEL] Changed the behaviour of CoreAttributes.ForEntity to no longer rely on a static cache, added a new overload with a caller supplied cache.
  • [WEB] <GridShell>'s right sidebar, if used, was not laid out on the correct grid tracks.

v310.2.1

Fixed

  • [WEB] Deleting an entity via a value reference field now cascades value deletions in the same way as WPF.
  • [WEB] Fixed bugs in the optimised <CommandBar/>, optimised it some more, and moved the actual optimisations to <CommandPanel> so that custom command presentations get the same benefits.

v310.2.0

Added

  • [WEB] New job type MessageConsumerJobBase<T>. When a consumer job FooJob is registered, you should also call FooJob.CreateChannel(IServiceCollection) to get a handle for message producers; this allows non-DI code to trigger events that use DI services.

    It can also be accessed inside the DI system by injecting IMessageChannel<T>.

Changed

  • [ORM] v310's change to AttributeBase.ToString() was more disruptive than anticipated, because PrimitiveAttribute<T> implements IValue<T> which makes ToString() part of the contract. To reduce the impact:
    • Added IValue.GetText() and deprecated ToString()
    • Renamed (Get/TrySet)[Original]Value to (Get/TrySet)[Original]Text
    • Restored ToString() on PrimitiveAttribute<T> until we've rooted out its callers

Deprecated

  • [ORM] entity.Delete() - the non-async version. .Kernel.MarkDeleted() still exists, but top-level Delete() is rarely what you want (DeleteAndPruneAsync() or DeleteAndCascadeAsync() are the alternatives).

Fixed

  • [SQL] Improved rerunnability of query tables setup script - it can no longer get into a bad state where it tries to drop a nonexistent constraint [FK__QueryEntity1].
  • [SQL] Migrator.MigrateDatabase() was losing the stack traces of sql exceptions it rethrew. It now restores them using ExceptionDispatchInfo.

v310.1.0

Added

  • [WEB] Roles provided by a registered IAuthorisation will now be available when using IIS authentication (which doesn't provide roles directly itself).

Fixed

  • [WEB] <CommandBar> off-by-n indexing.

v310.0.0

Added

  • [MODEL] Added NRTs to Instagile.Extension, which should cut down on IDE crashes.
  • [MODEL] Instagile.Model.Web is now compatible with the components and classes in Instagile.Web. The test site's "Model Editor" menu item will open an editor as a shell page.
  • [SEARCH] IReminderStore, an abstraction for counting reminders which may be remotely located. The main implementations are LocalReminderStore and RemoteReminderStore; as usual you'll get the remote one by default if an RPC endpoint has been registered.
  • [SQL] Extracted slow-query reporting into a utility class, The.Logging.TimedOperation.
  • [WEB] New job type PeriodicJobBase. Periodic jobs run on a regular interval, with policy settings for timeouts and slow-run detection.
  • [WEB] IReminderSource, an abstraction for subscribing to polled or pushed reminder updates, and IServices.Reminders (ReminderService) which multiplexes the subscriptions across different bits of UI.
  • [WEB] <ResponsiveShell>.Footer can now be any MenuModel.
  • [WEB] <ComboReferenceField> now supports IsReadOnly.

Changed

  • [ORM] AttributeBase.ToString() no longer evaluates the attribute (potentially updating calculated properties and raising events); instead, use GetValue() (and GetOriginalValue()), the mirror of TrySetValue().
  • [WEB] Reordered the parameters to JobBase.ExecuteOnceAsync() to make it clearer that you can supply either a startedBy Identity (to use JobRun recording) or an IProgress (to monitor the results yourself).
  • [WEB] Similarly, protected ExecuteOnceAsync() is now ExecuteJobAsync() to distinguish it from all the public methods by the same name.
  • [WEB] VacuumJob, MigrationJob and AddDataFix() have moved to The.Web.SQL. (The reason AddDataFix() has no The prefix is the same as AddJob() - it doesn't depend on having a framework services instance).
  • [WEB] Replaced Shell.<RemindersView> with Search.<ReminderMenu> and the corresponding ReminderLinkModel/RemindersMenuModel. Instead of polling internally, these links use a shared cache (see below).
  • [WEB] AddTheReminders() has moved from Instagile.Web.Frontend to Instagile.Web, as it's now shared between backend and frontend. It registers a ReminderUpdateJob which polls counts and acts as an IReminderSource, a ReminderUpdateQuery which is the backend for RemoteReminderStore and a ReminderUpdateCache which they both share.
  • [WPF] RemindersController now uses IReminderStore, which means that if you have an endpoint registered in your frontend you will need to AddTheReminders() in the corresponding backend. (Alternatively, see below.) RemindersController's configuration has grown; added RemindersOptions and a configure delegate to manage it. This can be used to set .Store to LocalReminderStore.Instance if you don't want RPC-based backend-cached reminders.
    RemindersController can be given "general" and/or "personal" reminders. General reminders are shared by all users and cached by the backend if one is used; personal reminders are polled client-side and therefore may use local state like username or the current date.

Fixed

  • [ORM] AttributeBase.DynamicValue was not evaluating transient OnDemand calculated properties until they'd been evaluated via the non-dynamic Value property.
  • [SQL] Fixed MigrationJob repeatedly generating schema if inspected.
  • [WEB] Checked <EntityListView> wasn't raising Command changes.
  • [WEB] Optimised rendering of <CommandBar> when some commands have async visibility checks - this used to produce flickering if you made rapid edits to fields on the page.
  • [WEB] Certain Command constructors would set visibility to always be true, ignoring the use of VisibleWhen().
  • [WEB] <ReadonlyField> wasn't binding, so it only read the attribute's value once. (This used to work before the <BoundProperty> optimisations in v309).

v309.2.0

  • [ORM] Added a new PermissionType: ExportEntities. Having the ExportEntities permission for a given entity type allows a user to export that entity type, including any other entities that can be accessed through relationships, so long as they also have the required read permissions.
  • [ORM] Breaking: PermissionSet has a new constructor parameter representing export permissions.
  • [ORM] Added Export, ReadExportAll and ReadWriteExportAll to PermissionSet.
  • [WPF] ListController and GridController will now hide export commands when the current principal does not have the required export permission.

v309.1.0

  • [WEB] Added <ListReferenceField> parameters Options and LoadOptions, which will be used instead of GetAll() to supply the available choices.
  • [WEB] ReferenceFieldBase's BindingReferenceChanged method is now virtual (like the equivalents in ValueFieldBase and CollectionFieldBase). It can be called to fake an update, or overridden to notify more things.

v309.0.0

  • [ORM] Breaking: The.ChangeTracking.NotificationExecutor's public field _Execute has been replaced with a method named Execute.
  • [WEB] Breaking: Removed FieldBase.OnValueChangedAsync and FieldSpec.OnValueChangedAsync; these cannot be implemented correctly because notifying from the dispather will unpredictably prolong the lifetime of mutations and other AsyncLocal users. The recommended replacement is to install entity/property-level event handlers.
  • [WEB] Introduced ReferenceFieldBase and ReferenceFieldBase<T> as a convenience base class for fields of EntityReferenceProperty[<T>]. We have a lot of these, which generally inherit from PropertyFieldBase because they don't want all the semantics of ValueFieldBase, but there's still duplicated code - reference changedness and rerenders work the same, even if the actual binding to the reference's data varies. Note that CollectionFieldBase already exists for the same reasons.
  • [WEB] The T in CollectionFieldBase<T> is now an entity instead of a property, for consistency with Value and Reference fields.
  • [WEB] Optimised validation to reduce rerenders.
  • [WEB] Optimised <BoundProperty> to reduce rerenders.

v308.0.0

  • [WEB] Breaking: Removed FieldSpec.
  • [WEB] Breaking: IEditSpec.LoadEntity is now LoadEntityAsync (it was previously async, but not correctly named) and takes a core context to indicate that it should only do data access work.
  • [WEB] Added IEditSpec.CreateEntity() (and equivalent virtual methods on DefaultEditSpec). This will be used by built-in screens that create new entities of that type for editing.
  • [WEB] <ListBox> and <ComboBox> now have the same themeable dropdown icon.
  • [WEB] Bugfix: Combinators on statically non-generic CellSpecs would discard non-customised headers.
  • [WEB] Bugfix: <FrontlineTheme> wasn't working in Firefox.

v307.1.0

  • [WEB] Fields will now remove any validation rules when hidden.
  • [WEB] The framework's CSS now includes default styles for #blazor-error-ui and .blazor-error-boundary, so apps don't need them. They can still do so in order to override these elements' appearance.
  • [WEB] Added an optional second NotAuthorized parameter to AuthorizedLinkModel and AuthorizedMenuModel.
  • [WEB] Improved consistency of <ListBox> with other widgets (styling <select> is not easy...)
  • [WEB] <ColumnsPanel> is more responsive.

v307.0.0

  • [SEC] IAuthorisation will no longer be asked to provide roles for Realm.Trusted identities.

  • [SEC] Added Credentials.PhoneNumber and Credentials.OneTimeCode to support SMS authentication. In theory, this could use Credentials.Username and Credentials.Password - but as a matter of defense in depth, it's best not to share credential types between authentication mechanisms.

  • [SEC] Added FailureCode.CredentialsIncomplete for multi-stage authentication mechanisms.

  • [WEB] Breaking: Icons have moved to The.Blazor.Controls.Icons.

  • [WEB] Breaking: lib.min.js is now just lib.js and lib.min.css is just lib.css; they will be minified in release builds of the framework, rather than debug builds including extra files.

  • [WEB] Frontend assets are now bundled with esbuild, removing the dependency on Node.js and reducing filesizes.

    • lib.css: 76KB -> 57KB
    • lib.js: 99KB -> 37KB
  • [WEB] Added <MenuIcon>, a typical three-bars "hamburger".

  • [WEB] Structured menus continue to expand with <BoundMenu> and RemindersMenuModel (which displays the installed reminders as a submenu).

  • [WEB] <BoxChrome> and <BoxButton> have AttachTop/Right/Bottom/Left properties to disable the corner rounding on that side of a box.

  • [WEB] When a <ComboBox>'s parent is rerendered, its text will be reset to the canonicalised form. This prevents bugs where controls that wrap ComboBox and use it asynchronously could set its Value repeatedly and yet end up with no text visible.

  • [WEB] <SidebarShell> can now switch back to the test theme from the production theme without reloading the page.

  • [WEB] <ResponsiveShell> is a lot closer to production-ready; deliberate placeholder elements have been removed and in theory it should function on all target devices.

  • [WEB] <SectionPanel> is more responsive.

  • [WEB] DefaultCriteriaSpec no longer produces (visible) criteria for BLOBs, Files and Images.

  • [WEB] Ongoing design tweaks, including:

    • Major typography overhaul. We now divide text into categories (UI, content, actions, technical); each gets its own font face and weight, with rem sizes for blocks and em sizes for inlines. System font stacks are used for each category to avoid bundle size increases and FOUC.
    • Themeable rounded corners for input widgets (controlled by --the-data-radius).
  • [WEB] Updated JS popover libraries to support pixel-accurate tooltip positioning.

v306.0.1

  • [WEB] Improved <ComboBox> keyboard shortcuts and hybrid keyboard/mouse usage - it should be fairly similar to The.WPF's ZomboBox (but it can't do everything).
  • [WEB] Command registration now has error handling - in the event of an error generating commands, the command panel will log the error and display it inline instead of blowing up the page it's on.
  • [WEB] <ValueReferenceField> had no type parameter and therefore could not register commands. Now it does and can.

v306.0.0

  • Building Instagile.Web.Frontend no longer uses wwwroot/ as a scratch directory, so the build should work regardless of what's in there. In the past we've had issues requiring either a clean or a build before pack. This was a bit tricky because officially, SWAs are only packed from wwwroot/ - we have to intercept and replicate part of the discovery process.

  • [SEC] Breaking: IAuthentication.CheckSignatureAsync and EncryptDataAsync now receive an Identity instead of a username. This allows authenticators to decide which realms' cryptography they understand; for example, SharedSecretAuthentication can sign anything but PasswordAuthentication can only work with passwords.

  • [SEC] Breaking: ComponentService.GetUserAccount and ModifyUserAccount now receive an Identity instead of a username. This allows the service to guarantee that it won't create account entities for forged data or for internal principals like those used by Jobs.

  • [SEC] Authenticators like PasswordAuthentication and PKIAuthentication, which map a method-specific login like a public key to an abstract username, were only performing this mapping in a client-server scenario. Now you will get an IPrincipal for the account even when using a single-tier app.

  • [SQL] Breaking: removed the error-hiding backwards-compatiblity method MigrationRunner.RunMigrations. Feel free to use TryRunMigrations and ignore the result if for some reason you don't care whether migration succeeded.

  • [SQL] Breaking: MigrationOptions has been split into MigrationRunnerOptions and MigrationJobOptions; formerly, MigrationRunner and MigrationJob used the same config even though they didn't both support all of it.

  • [SQL] Added The.SQL.Schema.Migrator, a simple (blocking, throwing) way to migrate in tests or non-web applications. It works the same way as MigrationJob, but with an overload-based API:

    Migrator.MigrateDatabase(options, new SQLMigrationRunner(db), schemaFile);
    

    or Migrator.MigrateDatabase(options, new SQLMigrationRunner(db), schemaFilename, entryPoint); or Migrator.MigrateDatabase(options, new SQLMigrationRunner(db), new SQLMigrationGenerator(), modelFile); or Migrator.MigrateDatabase(options, new SQLMigrationRunner(db), new SQLMigrationGenerator(), modelFilename, entryPoint);

  • [WEB] Breaking: ResponsiveShell's menu and footer are now modelled more formally as groups of links, rather than just a flat list. MenuModel and GroupModel will probably be used in other places in future.

  • [WEB] Bugfix: Fixed a DI cycle leading to a hang at startup when RemoteEntityStore was used together with SharedSecretAuthentication.

  • [WEB] Bugfix: Padding of <input type="date/time"> was shifting around in Firefox when focused.

  • [WEB] Bugfix: <ListBox> would sometimes throw FormatException when the user sets the selected value to null.

  • [WEB] Bugfix: <ComboBox> was not displaying a dropdown when Options was set.

  • [WEB] MigrationJob now uses the default entrypoint assembly when looking up schema or model resources; you can override it by setting MigrationJobOptions.EntryPoint.

v305.0.0

  • [OFFICE] Includes ExcelSpreadsheet changes from 290.3.1.
  • [WEB] Breaking: <MultilineBox> is now <BoxArea> (analogous to BoxInput, which wraps an <input>; BoxArea wraps a <textarea>).
  • [WEB] Design change: box-style widgets previously used colour to indicate focus and a border or outline to indicate changedness. Now it's the other way around - focused elements will have a thick border, and changed ones will have a colour, consistent with the colour changes used by other data states like invalidity.
  • [WEB] Added AuthorizedLinkModel.Resource - this works like Resource on [AuthorizationAttribute] and <AuthorizeView>.

v304.0.0

  • [MODEL] The model audit template will now allow for alert levels to be specified more than once for a particular violation type.

  • [MODEL] Added information level model audit alerts.

  • [ORM] Breaking: IOwnedSet has been removed - in practice, all IOwnedSets were also IEntitySets, and it conflated laziness with actual set operations.

  • [ORM] On the other hand, ILoadedSet has been added, a set interface which is guaranteed to be fully loaded and doesn't require async for any operations. IEntitySet.LoadAsync() will produce an ILoadedSet, doing work only if some elements of the set are not already loaded.

    Code like this: await foo.Bars.EnsurePresentAsync(); foreach (var bar in foo.Bars) { /* ... / } ...can be replaced with this: foreach (var bar in await foo.Bars.LoadAsync()) { / ... */ } LoadAsync() is more efficient than ToListAsync() as it doesn't make an extra copy of the collection.

  • [SEC] Added PermissionSet.Admin, PermissionSet.Read(types), PermissionSet.Write(types).

  • [SEC] Added ClaimsAuthorisation<T>, a ClaimsAuthorisation subclass which implements GetRolePermissions with declarative role mappings; override DefineRoles() and in theory, someday, you'll get automatically defined role-management UI.

  • [WEB] ICommandSpec is now a marker interface only; the new ICommandSpec<T> gives you actual typed entities to work with. Anything inheriting from DefaultCommandSpec<T> will work as before, except that it no longer requires a constructor parameter.

  • [WEB] Excised the "ContainingCollection" concept from CommandContext's public API - instead there's a new category, CollectionEntityCommands. EntityDeleteCommand is one of these, renamed to CollectionRemoveCommand (which is what it actually does - it never deleted anything!).

  • [WEB] <ListCollectionField> now supports all IEntitySets, not just EntityCollectionProperty.

  • [WEB] Fixed some broken bits of scaffolding and added test coverage.

v303.2.0

  • Includes changes from v301.2.0.

v303.1.0

  • [WEB] CurrentStatus has moved to The.Utility.
  • [WEB] Added JobBase.RunStatus and JobBase.CancelRun().

v303.0.2

  • [ORM] Bugfix: entity.Collection.ToEntityQuery().CountAsync() was failing because the query-container translation layer assumed that all queries have a signel generic parameter; hybrid queries have two.

v303.0.1

  • [WPF] Generated screens bugfix: for dependent features, the ConfigureSearch behaviour provider was being called for display screens instead of search screens (a compile failure).
  • [WPF] Generated screens bugfix: for features with dependencies, a prebuilt controller was not generated even if the dependent feature has behaviours.

v303.0.0

  • [MODEL] Breaking: Source generator-based templating is now explicit rather than trying to guess at a solution's structure - they vary too much. To emulate the previous defaults, add these items to your model project:

      <GenerateEntities Include="Foo.Model.theModel" />
      <GenerateProxies Include="Foo.Model.theModel" />
      <!-- If referencing Instagile.SQLServer -->
      <GenerateSQL Include="Foo.Model.theModel" />
      <!-- If referencing Instagile.WPF -->
      <GenerateScreens Include="Foo.Model.theModel" />
      <GenerateSpecifications Include="Foo.Model.theModel" />
      <!-- If you have custom features -->
      <ModelFeature Include="**\*.theFeature" />
    
  • [MODEL] Breaking: To allow moving the specification template output around, Entity.Specify() has been removed. For a while now this has just been a shortcut for new EntitySpecification(), which has all the same overloads - so to fix it, find/replace.

  • [MODEL] Breaking: ModelAuditOptions has moved to The.Model.Audit, along with ViolationType and AlertLevel. This means that...

  • [MODEL] ...Model auditing can now be done via source generation. Instead of generating ModelAudit.tt, add [assembly: ModelAudit(...)] attributes to configure the audit process.

  • [MODEL] Bugfix: In version 297, the editor began failing to load models that contained certain combinations of modelfeatures. This is fixed, and test coverage has been added to prevent it happening again.

  • [WEB] Addressed an edge case in composition which would cause AddTheScopedFramework to fail if two AuthenticationStateProviders had been registered before the framework (the second replacing the first).

v302.0.0

  • [SQL] Breaking: SQLOptions.SlowQueryThreshold is now nullable, rather than interpreting 0 as null.
  • [SQL] Breaking: SQLiteEntityStore now has an SQLOptions parameter type and a configure delegate, similar to SQLEntityStore.
  • [SQL] Performance improvement: SQLiteEntityStore batches together entity create operations in order to reuse their query plan; if your save consists of many inserts, this can be a large speedup. This work is part of a more general writeops fusion system, but InsertEntity in SQLite is the only enabled code path so far.
  • [SQL] Added SQLiteOptions.EnableSQLInjection for testing. In this mode, SQLiteEntityStore does no parameterisation of queries and sanitisation is up to the application. Do not use it.
  • [SQL] QIR.InsertStatement and QIR.UpdateStatement now work with arbitrary table expressions. Previously you could only update/insert into a table that had no alias.
  • [SQL] MigrationOptions.AuditConversionTimeZone now defaults to TimeZoneInfo.Local; since we don't have any pre-migration audit values left, it's only relevant for tests.

v301.2.0

  • [SEC] Added SecurityService.GetRolePermissions(Role), which returns a PermissionSet.
  • [SEC] Added IPrincipal.CheckPermissions(PermissionSet), which verifies that the principal has all permissions in the specified set.
  • [SEC] Instead of a single Permission, IReminder.RequiredPermissions is now a Predicate<IPrincipal>.

v301.1.2

  • [ORM] The generated FooProperties and FooInfo classes are once again partial. This allows application code to modify them, e.g. to implement interfaces.

v301.1.1

  • [SQL] Query translation now uses the potentially-optimised WHERE clause to eliminate unnecessary JOINs. A query of this form:

    var three = 3;
    var q = Human.Query().Where(h `=>` three == 4 && h.Owns.Value `>` 0);
    

    ... will no longer generate a join from Human to Farm.

v301.1.0

  • [MODEL] The WPF templates (Controllers.TT, Models.tt, Factories.tt) have been converted to source generators. <GenerateScreens Include="**\*.theModel"> will be added by default when referencing Instagile.WPF, or you can add it to the project that contains WPF screens.
  • [MODEL] Bugfix: Although non-source-generated templates still work, they'd lost the <auto-generated> xml comment which marks them as irrelevant to the IDE. Now it's back.
  • [UTILITY] Added a deconstructor for KeyValuePair<T, U>. This lets you write loops like foreach (var (k, v) in dictionary).

v301.0.0

  • .theLicence/.theModel/.theSchema files are now embedded as resources by default to save boilerplate.

  • All our builders and Add functions let you specify an optional "entryPoint" assembly, which is used to find those embedded files. In practice, it's not really optional... the default of the calling assembly is unlikely to be the one that contains the model, since we tend to use separate .Model projects. Calls like .Build(typeof(Entities).Assembly) are common.

    The entry point is still configurable, but the default has changed: if not specified, it's now the one that contains the generated entity types. In most cases this should be what you want.

  • [SEC] Removed Options.RealmClaimsMigration, which has been off by default for some time (see docs/identities-accounts-usernames.md for what it actually did). If by some chance we've missed migrating an ancient identity and someone cannot log in (I think GetPaid is the only app that would have this possibility), the fix is to add a Username to the victim's UserAccount.

  • [SEC] Removed Identity.Claims - this dictionary was used inconsistently and did not correspond either to the "permissions" provided by IAuthorisation or to the "claims" connected to an IUserAccount.

    In practice the only purpose it served was disambiguating identities produced by different authenticators (which deliberately do not compare equal). The Realm property has been brought back to serve this purpose; this time it's structured data instead of just a string. Account lookup and trusted principal creation are done by username instead of Identity; they use realms internally, but an app doesn't need to specify them.

  • [SEC] IAuthentication now has default implementations for the remote-authentication protocol - authentiators no longer have to implement sign/encrypt/lookup properties and methods if they don't support those functions.

  • [SEC] IAuthorisation now supports /named roles/ instead of "custom permissions". Permission/PermissionSet is reserved for low level things the framework itself can check and enforce. IPrincipal has new HasRole() and EnumerateRoles() methods, which applications can use for custom decisionmaking.

  • [SEC] ClaimsAuthorisation has been updated with role support; "admin" is the only built-in role (also still available via CheckAdmin()); you can set arbitrary ones with the AddRole() and RemoveRole() methods.

  • [UTILITY] Added a low-overhead EmptySet type which implements IReadOnlySet<T>.

  • [WEB] Login via CredentialsAuthenticationStateProvider now integrates IAuthorisation and ASP.NET Core roles. Roles produced by the authoriser will be available for [Authorize] attributes and <AuthorizeView> components, and roles produced by an external system will be available on IPrincipal.

  • [WEB] In order to prevent a combinatorial explosion when adding the above, composing Instagile.Web.Frontend has been made modular, similarly to the core and WPF layers. Instead of proliferation of special-case overloads of AddTheScopedFramework, the Register() calls on the builder or on the IServiceCollection can be used in whatever combination you like. For backwards compatibility, existing overloads have been retained with an [Obsolete] warning that explains how to replace them.

  • [WEB] Removed the ill-conceived Configure<TAppOptions>(), which was never noted here in the first place. Now it never will be!

  • [WEB] Added a simple <MultiListBox> - this works on both desktop and mobile, but differently; it is likely to be replaced later for consistency.

  • [WPF] Added virtual method ReferenceDataController.CreateBrowseController so that subclasses can more-easily customise how it opens entity data screens. By default this returns a SearchController<T>, but it can be any IController.

v300.0.0

  • [WEB] For clarity, instead of sharing a LinkTarget enum between DocumentView and LinkModel, LinkModel has a new subrecord - ExternalLink - and DocumentView has its own three-valued enum once again.
  • [WEB] <GridShell> and <ResponsiveShell> now have built in error handling, with appropriate recovery mechanisms and UI (<SidebarShell> already had it). You probably don't need to use <ErrorBoundary> directly in apps anymore, unless you want fine-grained error handling for specific parts of a dynamic page.
  • [WEB] <InputState> has been removed. We don't try to detect keyboard usage and allow browser-specific styles anymore - we just apply some designs to all controls that can be customised by an app, but not the underlying platform.
  • [WEB] The design system used by <SidebarShell> has been extracted into <FrontlineTheme>, which can be used with other shells. It also includes the custom font for which the original FrontlineShell (no longer extant) was designed.
  • [WEB] Added AuthorizedLinkModel, which (in <BoundLink>) displays a link only if the user matches an authorization policy or the default.

v299.0.0

  • [WEB] Added a new shell, <SidebarShell>, which was extracted from some intranet applications. It's only suitable for desktop apps, but it has a fairly mature design and may be a good choice for projects which need something production-ready but not the flexibility of GridShell or the mobile-friendliness of ResponsiveShell.

  • [WEB] <GridShell> can now handle a long header or footer by scrolling, although it won't look great.

  • [WEB] <StartupView> has a new parameter LoadingLayout. If set, apps that haven't started up will use this layout to render the LoadingContent (or the default placeholder).

  • [WEB] <ComboBox> now supports variable-height elements in the dropdown.

  • [WEB] LinkModel is now abstract, with a family of subclasses which produce different kinds of links (when rendered by <BoundLink>):

    • NoLinkModel doesn't go anywhere, just renders text.
    • DownloadLinkModel downloads an href.
    • NavLinkModel has an href and an active class based on the current route (using <NavLink>).
    • ActionLinkModel runs code (using <ActionLink>). The generic variant ActionLinkModel<T> will receive an injected dependency of type T.
  • [WEB] LinkMode is now LinkTarget and only applies to NavLinkModel. <DocumentView> uses LinkTarget? OpenTarget with null to indicate that it should be downloaded instead of opened.

  • [WEB] Fixed label positions on multirow fields - they now align with the baseline of the first row's text (if any) rather than being vertically centered.

  • [WEB] Fixed display of descenders on one-line (IsInline) notifications.

  • [WEB] Fixed <ValueReferenceField> displaying a visual error for a null reference.

v298.0.1

  • [WPF] Bugfix: Scrambling feature screen behaviours had #nullable enable, but incorrect annotations (they didn't mark entity references or document fields as nullable). This caused warnings in generated code.
  • [WPF] Bugfix: An automatic login that was "too fast" (no awaits) could call back into application code, via the SessionService.PrincipalChanged event, before IServices were fully constructed.

v298.0.0

  • [SEC] Some authenticators need supplied credentials to identify the user or log into a remote server. Previously this was done with IAuthentication.PushCredentials and ad-hoc features like PasswordAuthentication's two-args constructor. That works for desktop applications where there's a single IServices per user identity, but it doesn't work for web applications where client credentials may be needed on a shared server - for example, to validate a password.

    The.Security.Credentials is now an actual type, the union of supported credential kinds, and it's passed to client-side IAuthentication functions. Credentials are attached to a principal and provided to authenticators when necessary. You can supply Credentials when creating an IPrincipal with SecurityService or SessionService, but this isn't usually required; there's a current/global set of credentials stored in SecurityService for desktop applications and in user-scoped web applications (Blazor Server). In general, application-level APIs that 'consume' security haven't changed. Security 'producing' plugins have; IAuthentication and ILoginHandler now deal with credentials at the time of performing security checks, rather than as a stateful push process. Authenticators should now be stateless. (The only one which had additional state was PasswordAuthentication via its AddRule() method, which has been changed to a constructor parameter).

  • [WEB] Credentials-based web login now works in either webassembly or server modes. Instead of adding a The.Web.Backend framework instance with a separate authenticator, use the new overload of AddTheScopedFramework which lets you supply an IAuthentication factory (see GetPaid for an example).

    The new components <PasswordLoginForm> and <LogoutLink> can be used anywhere with a cascading authentication state to set/unset a login cookie by calling into the backend AccountControllerBase. AccountControllerBase still supports ASP.NET Core Identity (its original purpose), but this mode isn't as good an experience and we should use native login in cases when we have an implementation available of the desired authentication scheme. The new web login doesn't require a Post-Redirect-Get page load, and supports logout/user switching, either merely unauthorized from <AuthorizationView>'s point of view or truly unauthenticated if options.PermitAnonymousAuthentication is false. All modalities are saved in a cookie (if there's a backend to set one) which can be configured with the standard ASP.NET Core functions.

  • [WEB] <ActionLink> now blocks re-execution and becomes visually disabled until its command is done.

  • [WEB] <RowButton> is now <ActionButton> and also does this. It has a typed Action parameter to use instead of @onclick, although the latter remains supported for backwards compatibility.

  • [WEB] <RowDocument> is now <DocumentView> and lives in The.Blazor.Controls. Row____ names were confusing, and it would be the only one left.

  • [WPF] Bugfix: SuggestionField wasn't handling the new null-aware nature of ValueField well.

v297.0.0

  • [MODEL] Source generation is now optional - the obsoleted .tt templates work again, on top of the new template system. The default is still to use the source generator, but if you need to switch it off you can use <GenerateWhatever Remove="*.theModel"> and keep using the old system. docs/source-generation.md has been updated with a list of template/generator correspondences.
  • [MODEL] Bugfix: When executing concurrently, source generators could produce code that uses negative array indices for core attributes.
  • [ORM] Breaking: The.Values.Box now tracks nullability - Box<T> implements IValue<T> rather than IValue<T?>. Consequently, it no longer has a 0-arg constructor.
  • [ORM] More NRTs, in fairly arbitrary places.
  • [SQL] Instagile.SQLServer and Instagile.SQLite now have full NRT coverage.
  • [WEB] <Checkbox> and <NullableCheckbox> now support splatting arbitrary attributes, which are passed through to a hidden <input> tag.
  • [WPF] NRT annotations for most fields. ValueField<T> no longer has a zero-argument constructor - it requires either an IValue or an initial value. (You can use FieldFactory to get the framework's default value for various types - FieldFactory.CreateInteger() instead of new ValueField<int>()).
  • [WPF] Generated screens (Controllers.tt, Models.tt and Factories.tt templates) now have full NRT coverage.

v296.2.2

  • [ORM] Fixed a bug in the EntityInfo template which prevented instantiating entities with legacy collections using in-memory persistence.

v296.2.1

  • [WEB] Added <ColumnsPanel Unbalanced> - a flag which will lay out cells vertically up to the height limit (if any) of the container, before adding columns.
  • [WEB] Fixed criteria view in Chrome 91+ rendering at half-height when there was exactly one criterion.

v296.2.0

  • [MODEL] The Specifications.tt T4 template has been replaced. <GenerateSpecifications Include="**\*.theModel"> will be added by default when referencing Instagile.WPF, or you can add it to the project that contains WPF screens.

  • [MODEL] Now that code generation is done by the build system, we can make it configurable. "Legacy" types, used for raw access to soft-deleted data, are not used in most applications and they add a lot of code. Model.Namespace.Legacy classes will no longer be generated unless property GenerateLegacyTypes is set. To enable this for an entire solution, add this to Directory.Build.props:

    <PropertyGroup>
      <GenerateLegacyTypes>True</GenerateLegacyTypes>
    </PropertyGroup>
    

v296.1.0

  • [MODEL] Fixed bugs discovering template inputs when a project contained <AdditionalFiles> other than a single .theModel.
  • [WEB] Added JobBase.Logger for the use of subclasses. Eventually, the logs written through this logger will be captured in some useful way. That doesn't happen yet, but it does log them!
  • [WEB] MigrationJob now allows specifying a model path or file instead of a schema path or file. In this mode, it will generate the schema on the fly. This is a time/space tradeoff which may provide useful flexibility when a model is frequently changing.

v296.0.0

  • [MODEL] Breaking: Some code generation is now done by a source generator in Instagile.Analyzers instead of loading T4 templates using the Instagile extension. .theModel and .theFeature files in a project will be automatically discovered; to add or remove extra inputs, add items to your project file (see docs/source-generation.md for more details)

    The generated types haven't changed significantly, but some T4 templates are now obsolete and and their corresponding output files should be deleted.

  • [MODEL] Breaking: CommonProperties has moved to The.Model and been renamed to CoreAttributes. It's used by templates as well as the runtime, and describes things in modelling rather than runtime-info terms.

  • [MODEL] Added SnapshotBuilder.BuildFromEvents() and BuildFromModelAndChanges() overloads which take a cancellation token. The token will be checked after processing each event.

  • [MODEL] Added The.Utility.Result, a type similar to Optional for passing around a value-or-error. Result.Create(f) will produce a Result<T, Exception> by wrapping the delegate f in try-catch.

  • [WPF] Added ScreenControllerBase.ModelBound, a Task which can be awaited by subclasses that will complete when the controller's model is fully initialised (or cancel when it fails to initialise). This can be useful for screens with a complex setup that also need to install callbacks to the screen itself, so that the callbacks don't run too early; ContentControllerBase uses it to solve a race condition which arose when we started loading the content subscreen earlier in DisplayController.

v295.1.0

  • Added a compile-time white-labelling feature. In a project file or Directory.Build.props, use <WhiteLabelEnabled>True</WhiteLabelEnabled> and set a WhiteLabelBrand (from a build server, environment variables, etc). This will set #define BRAND_<label> and add a [WhiteLabel("<label>")] attribute to the assembly.
  • [WEB] .UseWhiteLabel() host extensions which add extra config files using the brand as a pivot (for example, appsettings.Agile.Development.json).

v295.0.2

  • Breaking bugfix: Criteria, Search and SearchModal screen controller base classes no longer provide a convenience constructor which converts IQueryable to IEntityQuery. This apparent backwards-compatibility feature was a trap, because it would silently prevent controller overrides from being discovered if they called the wrong base class constructor. This deliberate break only applies to screen subclasses, not screen consumers; ScreenService still supports the use of queryable factories instead of query factories.

v295.0.1

  • [ORM] Bugfix: CreateQueryable().Where(/.../).Freeze().ToEntityQuery() was failing.

v295.0.0

  • [ORM] Introduced a new type IEntityQuery, which will replace our use of IQueryable. At the moment it's almost the same as IQueryable, but will be customised in future to better suit our entity system. Conceptually, an entity query is "inert", and can be used to load data into a context or to search an existing datasource; unlike a queryable, it doesn't represent a datasource itself.

    • Entity.Query(), IEntityInfo.Query() and PersistenceService.CreateQuery() now return an IEntityQuery<Entity>.
    • Framework APIs that accept queries or query factories have been given an extra overload with the new query type.
    • Both IEntityQuery and IQueryable are supported by all entity stores for now.
    • IEntityQuery is mostly identical to IQueryable, but there is a crucial difference: it isn't a subtype of IEnumerable. To iterate it, you need to call a reification operator like ToListAsync() (or ToList(); sync reads are not yet prohibited).
    • Extra methods are available for backwards compatibility: PersistenceService.CreateQueryable() can be used to create an IQueryable<Entity>. IQueryable has a new extension method ToEntityQuery(), and IEntityQuery has ToQueryable(). These may be deprecated in future depending on how well the transition goes.
  • [ORM] LoadGraphAsync() and GetGraphLoadOperations() have moved to The.Entities.GraphNavigation - previously they were extension methods on IEnumerable<IEntity>.

  • [ORM] Fixed CutoffFrozenQuery optimisation (date-based GetAll()), which hasn't worked for a while.

v294.3.0

  • [SEC] The default for Options.RealmClaimsMigration has changed from true to false - these migrations are largely or entirely done.
  • [WPF] Optimised startup and login performance.
  • [WPF] Added DisplayOptions.UseContentPlaceholder, which is true by default. If set, a blank content screen will be displayed while long initial entity loads are occurring.

v294.2.0

  • [RPC] Breaking: AuthenticationFailure no longer just an error code; it's a class with the code and an optional "Cause" exception. These will be supplied in cases like InternalError or PermissionLookupFailed when a non-security issue caused a security problem.

  • [RPC] Improved logging and error handling for serialisation.

  • [TEST] Instagile.Xunit has a new logger which can capture logs in test output. Example of use:

    public class Tests(ITestOutputHelper helper)
    {
        [Fact] public void TestFramework() 
      {
          var services = new The.Composition.Builder().ConfigureLogging(options `=>` options.AddXunit(helper)).Build();
      	// use services
        }
    }
    
  • [WEB] Custom <SectionPanel>s now have constrained content, allowing them to be scrolled either internally or externally (if a <ScrollPanel> is used).

  • [WEB] <BoundLink> produces an <a disabled> when its href is not set.

  • [WEB] <ResponsiveShell>'s footer is now optional, and will expand if necessary to fit many elements.

  • [WPF] Bugfix: ExternalInstall would continue to attempt to update even if the update service was not detected.

v294.1.0

  • [WPF] Updates using ExternalInstall will now test for the presence of the named pipe before trying to connect to it, display an error message if it isn't found.
  • [WPF] ExternalInstall has some new fields so apps can customise the message shown to users when the external update service is not detected.

v294.0.0

  • [MODEL] Bugfix: Model features could be automatically marked as upgraded without their upgrade events being recorded.
  • [WPF] Builder's OnLogin() and OnLogout() no longer replace any delegates that were previously set on the builder; instead, they add new delegates that run in sequence.
  • [WPF] Breaking: UseIntegratedLogin() no longer has a special passthrough for delegates to run first.
  • [WPF] Non-ShowOnForm properties will no longer be included as available grid columns by default; set GridOptions.IncludeOnlyShowOnFormColumns to False to restore the old behaviour where a user could add any column.

v293.0.0

  • [WPF] Breaking: ScreenService.EntitySaved has been replaced with EntitiesSaved, which can handle notifications for multiple entities at once, and has a new flag that specifies whether a saved entity was "top-level" i.e. was it the root entity for a Create or Display controller.
  • [WPF] Breaking: Removed ScreenService.NotifyEntitySaved.
  • [WPF] Breaking: Some TabbedShell constructor parameters have been combined into ShellOptions, likewise for AutoUpdater -> UpdateOptions, and both can be set on IntegratedLoginOptions.
  • [WPF] AutoUpdater can now be given an InstallMethod subtype to specify how to install. The default SelfInstall() is the existing method; ExternalInstall() has been added, which writes a json-serialised UpdateTrigger to a named pipe (this is the protocol used by Tortosa).

v292.5.0

  • [MODEL] Attributes have a new IsUnique flag which indicates that no two entity instances should have the same value for the attribute; null is excluded for this rule. For example, if an Integer attribute is marked as unique, then it can be 1 on only one entity (or no entities) at a time, 2 on only one entity at a time, and so on, but it can be null on any number of entities. To begin with, IsUnique is supported only in SQL Server; other persistence backends will ignore it.

v292.4.0

  • [ORM] Added a fast path to SecureStore so it returns immediately if asked to read or write with no ops.
  • [ORM] Bugfix: LoadGraphAsync could lose track of some known entities and possibly load the wrong amount of data.
  • [WPF] When GridOptions.CanManageColumns is set to false, column visibility and order preferences will be ignored.
  • [WPF] LinkBox no longer decides on its own whether to show a link or not; set its new IsNavigable property to control that.
  • [WPF] LookupInlineReferenceField has a new canNavigateOverride constructor parameter that can be set to override whether a link will be displayed when the field is not in selector mode. By default the previous behaviour (hide the link only for reference data) is preserved.
  • [WPF] Bugfix: ContentModel.FindField would not find fields by property name if they were wrapped.
  • [WPF] SectionedCollectionFieldBase now implements IBoundField.

v292.3.1

  • [ORM] Entity classes' static Metadata field is now a property.
  • [ORM] DeploymentUtilities.DownloadFilesAsync() now supports non-incremental downloads.
  • [WPF] Set GridOptions.CanManageColumns to false to prevent users from changing the columns in a Grid screen.

v292.3.0

  • [ORM] Moved parts of The.WPF.AutoUpdater to The.Management.DeploymentUtilities so that they can be reused for non-GUI updates.
  • [SQL] Bugfix: ShouldConstrainLegacyRelationships would attempt to create or drop foreign keys and indexes that had already been created (due to legacy SQL migration patterns) or had never been created respectively.

v290.3.0

  • [EXPORT] Added The.Office.Export.Currency and ExcelSpreadsheet.UpdateValue/UpdateCell overloads for it. This replicates the default "Currency" style in Excel, which is not actually a number format - it's a string template created on demand.

v292.2.0

  • [MODEL] There is a new ShouldConstrainLegacyRelationships model property which controls whether persistence enforces uniqueness and referential integrity constraints for legacy relationships. The default value is True, preserving current behaviour. It's expected that at some point in the future, all applications will have this property set to False, and at that point we can remove it.
  • [SQL] Tables for legacy relationship no longer have generated foreign keys when ShouldConstrainLegacyRelationships is set to False.
  • [SQL] Unique indexes are generated for non-collection relationship sides. These indexes are no longer unique for legacy relationships when ShouldConstrainLegacyRelationships is set to False.

v292.1.1

  • [ORM] Bugfix: EntityKernel.PruneLoaded will now also remove itself from the other side of navigable relationships.

v292.1.0

  • [SQL] Added SQLOptions.MeasureExecutionPlans, which can be set to a callback to dump readops and writeops' execution plans (as .sqlplan XML).
  • [SQL] Bugfix: SQLOptions.UseIsolationStatements was immutable.
  • [SQL] Bugfix: When SQLEntityStore enabled autonum modification for special purposes, it didn't turn it off again - which could have lead to autonums not incrementing further.

v292.0.0

  • [SQL] ReadUncommitted() is now WithReadUncommitted().
  • [SQL] Fixed a bug using [With]ReadUncommitted() for queries that don't refer to physical tables - for example, the aliased sub-select that's generated by a pattern like .OrderBy().Take(1).Select().
  • [SQL] Added SQLOptions.UseIsolationStatements, which is on by default. When set, each batch will begin with a SET TRANSACTION ISOLATION statement. In this mode, WithReadUncommitted(), will change the isolation level instead of using WITH (NOLOCK); it will do nothing unless set for all queries in a batch.

v291.4.0

  • [SQL] TSQLDML and SQLiteDML are now public, for the use of tests or low-level code which needs to turn QIR into SQL.
  • [SQL] New entity query operator .ReadUncommitted(), which is an optimisation hint - when executed against SQL databases, it literally applies the READ UNCOMMITTED isolation level. This permits dirty read anomalies, but it can be a significant performance improvement in cases where stale data is acceptable.
  • [WEB] <EntitySearchView>, <ReminderPage> and <ComboReferenceField> use .ReadUncommitted() to trade-off stale reads for performance.
  • [WEB] Added entity view placeholders: <LoadingListView>, <LoadingCriteriaView>, <LoadingSearchView>, <LoadingEditView>.
  • [WEB] Built-in pages use placeholders to improve time-to-UI when the database is busy.
  • [WEB] Bugfix: <EntityCriteriaView> was being rendered on pages with no visible criterion.
  • [WEB] Bugfix: <ComboBox> dropdown didn't close when tabbing away while hovering over an option.
  • [WPF] CriteriaController, RemindersSidebar and EntitySelector use .ReadUncommitted() to trade-off stale reads for performance.

v291.3.0

  • [ORM] Fixed bugs cloning an entity with an unloaded reference into a context which contains the reference's target. The relationhip will now be hooked up immediately, rather than remaining !IsPresent until someone accesses .Value.
  • [ORM] Fixed bugs merging a context which contained entities with unloaded references with a context which contains the reference's target. As above, the relationship will be hooked up on the spot.
  • [WEB] PageService.GetClientDownloadLink() - this returns a LinkModel, as an alternative to using the component <ClientLink>.

v291.2.1

  • [WEB] Fixed command status not updating on rerender in the new <CommandBar>.

v291.2.0

  • [ORM] The modelled empty text fallback value now also has a fallback value of "(not set)" if it is also empty (which is the default).
  • [WEB] <ReponsiveShell> now supports the iOS viewport and notch.
  • [WEB] OptionsQuery is now a public parameter of <ComboReferenceField> allowing overriding of the default query.
  • [WEB] It's no longer necessary to cascade a ValidationContext into <EntityEditView> - it will create its own if none is provided.
  • [WEB] <CommandRegistration> has a new Validate parameter which allows the installation of a ValidationContext into the CommandContext, regardless of their relative positions in the component hierarchy.
  • [WEB] Fixed some bugs where certain validation rules would not apply to relevant commands, based on race conditions in the creation of ValidationContexts.
  • [WEB] New component <CommandPanel>, which is the abstract part of <CommandBar> - a view that can display and execute commands given some arbitrary UI. It has one slot, a RenderFragment<CommandsModel>, which provides an AST which specifies the currently available commands and their state for rendering. <CommandBar> still exists as a specific command presenter, with no logic of its own.

v291.1.0

  • [WEB] Improved ResponsiveShell padding and added an AppTitle property (if not set, Options.AppName will be used).

v291.0.0

  • [WEB] Breaking: The.Blazor.Entities.PageContext is now LinkContext.
  • [WEB] Added an unrelated interface IPageContext in The.Blazor.Commands. Shells or layouts may optionally cascade an instance of this type; if a <CommandedPage> is inside such a shell, it will delegate presentation of its chrome (titlebar, command buttons) to the shell itself.
  • [WEB] New component <ResponsiveShell>, an alternative to <GridShell> which uses media queries and IPageContext to adapt app ui to different screen sizes.
  • [WEB] Added <CommandedPage>.CommandContext (a public property, not a parameter), which can be used to orchestrate commands externally. This is equivalent to the existing property on <CommandedView>.
  • [WEB] <CommandBar /> can now be used without a cascaded CommandContext - it just won't display anything. This is useful for UI which may or may not contain externally-supplied commands.
  • [WEB] Added <EditPage.LoadEntity>, which lets you supply a custom entity without going through ScaffoldService.

v290.2.0

  • [EXPORT] Added UnmergeRange() to ExcelSpreadsheet and ExcelWorksheet.

v290.1.0

  • [EXPORT] ExcelExportFormat can now use typed cells (number/date format) for custom columns with no AttributeInfo.
  • [ORM] Added EntityQueryExtensions.GetGraphLoadOperations which functions like EntityExtensions.GetGraphLoadOperations but can produce read ops when no data has been loaded. Also supports some scenarios where some data has been loaded, such as when using a query produced from an unloaded collection property.
  • [ORM] Bugfix: AttributeTypeInfo<T>.DefaultValue is now recalculated on each invocation, which restores the v289 behaviour for newly created temporal attributes, such as createdOn.

v290.0.0

  • [EXPORT] CSV export sanitising had a spelling mistake which meant en dashes weren't being corrected.
  • [EXPORT] Excel export was overcounting rows when exporting through collections, producing an inaccurate progress bar and logged warnings.
  • [EXPORT] ExcelSpreadsheet can now detect that merge cells already exist and avoid creating invalid spreadsheets with a duplicate merge.
  • [EXPORT] ExcelSpreadsheet truncates worksheet names beyond the 31-character maximum instead of producing invalid files.
  • [ORM] Breaking: PrimitiveAttributeBase<T> and its subtypes have been replaced with PrimitiveAttribute<T>, which pulls type-specific behaviour from an AttributeTypeInfo<T>. Document attributes are still handled separately for the time being.
  • [ORM] Bugfix: the logging category for save tracing was STILL the name of The.Persistence.Write.SavePlanner after mangling by obfuscation, which STILL cannot reasonably be typed into a config file.
  • [ORM] Bugfix: AppDataPreferenceStore could get stuck in a bad state with an empty invalid XML file.
  • [ORM] Added DeleteAndCascadeAsLoaded and GetAllAsLoaded to perform the same function as their async counterparts but throw if not loaded.

v289.1.0

  • [EXPORT] IColumn.Map() supports changing type (Func<T,U> instead of Func<T,T>).
  • [EXPORT] Added built-in FixedColumn and CalculatedColumn implementations for custom exports.
  • [EXPORT] ExportParameters is now a withable record.
  • [EXPORT] Null cells can now be given a style.
  • [EXPORT] Fixed exploded-collection row calculations.
  • [WEB] <AsyncCommandedPage> flags default to false like <CommandedPage>.
  • [WEB] <FieldRow> layout, which was broken by the unification of the grid and table versions, is fixed.

v289.0.0

  • [EXPORT] Add method Reverse() and property IsNavigable to RelationshipPath.
  • [EXPORT] Export can now explode collections across multiple rows (with other cells left blank). IColumn.GetValue() has been replaced with GetValues(), which navigates all collection members when encountered in a RelationshipPath; GetText() still returns a single summary cell. Consequently, ExcelExportFormat uses exploding by default but CSVExportFormat does not. (Previously, ExcelExportFormat would throw an error if asked to generate a column for a property like Foos.Bar, so this is not a breaking change).
  • [EXPORT] Instead of requiring a .xlsx template, ExcelExportFormat now takes a parameter struct which gives applications some control over the output. A template can still be used optionally via the parameters, but you don't need one to customise text and column sizes, worksheet naming and numbering, numeric formats or the placement of borders.
  • [MODEL] Bugfix: Template generation, when attempting to report an error, would fail to serialise invalid characters in obfuscated type and member names.
  • [WEB] Changed the default for CanCreate/CanDelete parameters on <CommandedView> and <CommandedPage> from true to false. Controls like <BrowsePage> that want the ability to create entities should set CanCreate="true". With the default the other way around, a lot of pages that embed an <EntityListView> were getting unwanted Create commands.
  • [WEB] ListCollectionField and ValueReferenceField now support IsReadOnly.
  • [WEB] Removed the hidden div from <LoadingTitleBar> - using a different number of child elements made it hard to create consistent layouts. You can target titlebars in loading state with CSS class .the-title-bar--loading.
  • [WEB] <LoadingPlaceholder> now supports rendering different tags dynamically. Consequently, all elements that display 'Loading...' text now have the same .the-loading-placeholder class for theming.
  • [WEB] Tag-wrapping components that support a splat (<BoxInput>, <RowButton>, etc.) will now merge classes that are supplied in the splatted attributes into their own class list. This replaces the inconsistently-available ExtraClasses parameter.
  • [WEB] Bugfix: <CommandRegistration>.AddAsync() could reenter (rather than being once-only) if an external rerender occurred while the provided command iterator was awaiting.
  • [WPF] The export UI has been updated to support collection navigations.

v288.1.0

  • [MODEL] There is a new "Copy entity with relationships" command which makes a copy of the selected entity and all of its relationships.
  • [WEB] Bugfix: FieldRow and FieldGrid no longer use different layout for Chrome and Firefox, which should fix layout shift between prerender and blazor-render

v288.0.2

  • [WPF] Bugfix: ReloadableField did not keep track of validation rules after applying them to its inner field, causing them to be lost when reloading.

v288.0.1

  • [WPF] Bugfix: InlineCollectionFieldBase used the synchronous Dispatcher.Invoke when handling CollectionChanged, causing a deadlock in an application.

v288.0.0

  • [WPF] Breaking, bugfix: all screens have a principal which they receive from their surface (using an untrusted principal as a fallback). Create and CreateModal screens usually created their entity in a new context without providing a principal, which would lead to a NullReferenceException. There was a way to provide a custom principal for this purpose, but Search screens did not provide one. This is fixed with two breaking changes:

    • Create and CreateModal screens' entity factory delegate must now take an IPrincipal parameter, to which they will pass their own principal.
    • ScreenService no longer provides CreateCreateController or CreateCreateModalController overloads that take an IPrincipal parameter, as it will not be used. The CreateCreateController and CreateCreateModalController overloads that take a prebuilt entity parameter still exist, but should be used with caution as the entity's principal is not necessarily the same as the screen's.

v287.3.0

  • [WEB] Added type The.Blazor.Composition.InternalServices, which has static methods for doing parts of composition 'by hand' - this is useful for tests and other weird integrations.
  • [WEB] IPageSpec overrides now receive a PageContext with the current services.

v287.2.0

  • [WEB] <StartupView> can now be used without any StartupRequirements, for apps which add requirements dynamically.

v287.1.1

  • [WEB] Added <CommandRegistration OnCleanup="this runs when commands are removed, due to dispose or replace">.

v287.0.0

  • [ORM] Breaking: ExportParameters now accepts, and requires, a principal. Exporting may use multiple contexts for performance reasons, and this principal is used to create them.

  • [WEB] Breaking: full-page components now end with Page - so <Browse>, for example, has become <BrowsePage>.

  • [WEB] Instagile.Web.Frontend's CommandContext subsystem supports the decoupling of business logic actions and the UI that presents them. It was flexible, but finicky; in this release it's been formalised in order to preserve advanced scenarios while making commanding easier to use. Detailed Debug-level logging has been added to diagnose any issues with the changes.

  • [WEB] New namespace The.Blazor.Commands containing a number of types:

    • Command has moved from The.Blazor.Entities, but is otherwise unchanged.
    • CommandContext has moved from The.Blazor.Entities, and no longer exposes a public mutable list - commands should be registered using the components below.
    • <CommandedView> creates a named subtree that can host commands. Commanded trees will automatically reuse outer contexts if necessary in order to hoist UI; otherwise, they will propagate notifications downward.
    • <CommandedPage> uses <CommandedView> to implement the standard titled-page UI; it's used by the built-in pages, and apps can use it on custom pages to create a matching look. <LoadingCommandedPage> and <ErrorCommandedPage> are inert variants used to display consistent placeholders. <AsyncCommandedPage> is a convenience wrapper which puts all three of them inside a BoundTask.
    • <CommandBar>, which should be used inside a commanded region, displays the current context's commands in a specific form (a bar of buttons). We can add more command-hosting UIs as needed.
    • <CommandRegistration>, which should be used inside a commanded region, modifies the current context's commands - replacing or adding to the list. It handles debouncing, and since it's part of the component tree @key can be used to to control command re-generation.
  • [WEB] <TitleBar> and <LoadingTitleBar> have moved to The.Blazor.Controls. <TitleBar> no longer implicitly contains commands; both its title area and its command area can contain arbitrary fragments.

  • [WEB] CellContext no longer serves any purpose, and has been removed. Cells can add associated row commands with a <CommandRegistration> if necessary.

v286.0.0

  • [ORM] Breaking: Predicates.Like has been removed.
  • [SQL] Bugfix: Queries that use the LIKE string operator (e.g. Contains, StartsWith) were not correctly escaped when generated for SQL Server.

v285.0.1

v285.0.0

  • This release contains deliberate API-breaking changes, to prevent a problem when upcoming features change the semantics of these APIs.
  • [WEB] Instagile.Web, Instagile.Web.Frontend and Instagile.Web.Backend now require .NET 7.
  • [WEB] The.Blazor.IEntityContext is no longer injected. This type had a transient lifetime, which is not generally useful; most of the time, it's best to inject The.Blazor.IServices and call CreateContext() intead.
  • [WEB] The.Web.IEntityContext and The.Blazor.IEntityContext no longer shadow core IServices with their own IServices. The.Blazor.IServices and The.Web.IServices can be obtained by @injection.
  • [WPF] The.WPF.IEntityContext no longer shadows core IServices with its own IServices. The.WPF.IServices can be obtained from an ISurface or screen base classes.

v284.2.2

  • [WEB] Prevent tabbing on to the X button on a combobox to improve the user experience when using keyboard only
  • [WEB] Prevent extra indentation when an empty string label is used, by treating empty string label as unlabelled
  • [WEB] Bugfix: Fixed issue in ComboBox widget where unstyled options flashes on the screen momentarily when opening the drop down

v284.2.0

  • [ORM] Changed InvalidatedAssertion Time property to a DateTimeOffset so that its clear that it contains UTC time.
  • [ORM] VersionConflictException now correctly converts the Time to local time for display purposes
  • [WEB] <RemindersView /> now automatically updates reminder counts; this can be disabled or configured with the new UpdateFrequency parameter.
  • [WEB] Improved CommandBar and NotificationView to display Message AND DetailedMessage rather than either or.
  • [WEB] Improved the logic around when to preformat error text in NotificationView, and allowing this to be specified as a parameter

v284.1.1

  • [WEB] Bugfix: Prevent double-clicking a Command button (disabled while executing)

v284.1.0

  • [SQL] SQLiteDatabase is now thread-safe, using the connection pooling in an updated version of Microsoft.Data.Sqlite.
  • [SQL] Added The.Sqlite.MemoryDatabase, which uses in-memory sqlite with a shared cache to make it pool-compatible.

v284.0.0

  • [ORM] Bugfix: the logging category for save tracing was the name of The.Persistence.Write.SavePlanner after mangling by obfuscation, which cannot reasonably be typed into a config file.
  • [WEB] Breaking: ManualJobBase is now in the The.Web.Jobs namespace instead of The.Test.Site.
  • [WPF] Breaking: GridColumn is now a record with only properties and a ToString override.
  • [WPF] Technically breaking: the ReferenceData screen now includes a button on each entity row that allows user with write access to that entity type to trigger recalculation of all properties on it.

v283.2.1

  • [ORM] Bugfix: Fix GetUserAccount only comparing the required claim values to the identity's claims and not the claim key when running in "temporary backwards compatibility mode".
  • [ORM] Bugfix: The temporary backwards compatibility mode for GetUserAccount would sometimes be invoked without any claims, leading to queries like UserAccount.Query().SingleOrDefault().
  • [WPF] Bugfix: GeneratedControllerFactory would not make use of "prebuilt" content controllers if the feature declaring that entity type lacked any screen overrides, even if other features with screen overrides for that table were enabled.
  • [WPF] Bugfix: BLOB fields would enable their download button even when no value was set.

v283.2.0

  • [WEB] Raise ValidationResultChanged event on ValidationContext and remove relevant notifications from CommandBar if there are no more validation errors

v283.1.0

  • [MODEL] Bugfix: The editor didn't process events that caused a non-calculated property to become calculated correctly - it would require you to change its mode a couple of times pointlessly to get in sync with the model file.
  • [WEB] Bugfix: Fix Uri in wrong format when resetting criteria for current page.
  • [WEB] Bugfix: Fix styling of notifications in the command bar.
  • [WEB] Always show IsSmall notifications below the command bar.
  • [WEB] Bugfix: Fix issue with multiple calls into OnParameterSetAsync causing issues with criteria view when there are async criteria

v283.0.1

  • [WEB] Bugfix: QueryString no longer appended to outgoing links when navigating away from Browse page

v283.0.0

  • [ORM] Breaking: WellKnownComponents has been removed. Please use a FeatureCollection instead.
  • [SQLITE] Bugfix: SQLiteEntityStore was unaware of some model feature interfaces.
  • [WPF] Bugfix: List column bindings were still referring to "props".

v282.0.1

  • [MODEL] Bugfix: ApplicationSettings and UserRegistration features were accessing "kernel" in their format strings.

v282.0.0

  • [ORM] Breaking: EntityBase.props has been renamed to Properties. Applications may need to modify some modelled entity Text format strings in accordance with this change.
  • [ORM] Breaking: IProps has been renamed to IEntityProperties. All feature IProps have also been similarly renamed.
  • [ORM] Breaking: EntityBase.kernel has been renamed to Kernel. Applications may need to modify some modelled entity Text format strings in accordance with this change.

v281.0.1

  • [WEB] Fixed multiple bugs in querystring synchronisation when using <EntitySearchView>.
  • [WEB] Fixed updating <NumberTraitsBox> parameters multiple times without intervening user input - this failed to rerender.

v281.0.0

  • The.Tool can now be supplied with theFeature files when generating code by using the -f or --feature option.

  • [EXTENSION] Instagile.Extension can now detect application-defined model features. It will scan the Generated, GenOnly and Model folders for any .theFeature files and include them in the FeatureCollection that it supplies to the model editor and template runner.

  • [MODEL] The editor hosted in Instagile.Extension will now be aware of any application-defined features detected by Instagile.Extension.

  • [MODEL] Sections and relationships defined by a model feature will now appear locked in the editor.

  • [MODEL] The editor will now ensure that when adding a model feature, any dependencies are also added first, and the inverse when removing a model feature.

  • [MODEL] Breaking: IFeature has a number of new and altered properties to support application-defined model features.

    • Dependencies is a list of feature dependencies by their Name property.
    • CalculationProvider refers to a class that implement attribute calculation methods via static methods. If you include the assembly name then the Entities template can copy the CalculationDependency attributes into generated code.
    • CalculationMethods is a mapping of attribute ID (or entity ID for IEntity.Text) to a method name that exists in the CalculationProvider.
    • IsPresentUnversioned() has been moved to FeatureExtensions and now operated based on the table IDs in the new property FirstVersionTables.
    • ScreenBehaviourProvider refers to a class that implements various screen behaviour overrides via static methods.
    • The.Model.Features.Table now includes a list of section IDs that were added by the feature.
    • The.Model.Features.Table has a new parameter IsDependency to indicate that this entity table was defined in another feature and is being augmented by this feature.
    • Remove() has been moved to FeatureExtensions and is now calculated based on a feature's other properties.
  • [MODEL] Breaking: InterfaceName has been renamed to TypeName to reflect the fact that it is now being used to refer to some non-interface types.

  • [MODEL] An IFeature can now specify that it has a dependency on one or more other IFeatures.

  • [MODEL] The UserRegistration feature now depends on the UserAccounts feature.

  • [MODEL] IFeatures can now be serialised into a '.theFeature' file, represented at runtime as a FeatureFile object.

  • [MODEL] The Features property in TemplateBase will now contain any application-defined features detected by Instagile.Extension.

  • [MODEL] ModelFile has a new Features property which can be used to make it aware of application-defined model features. After deserialising or constructing a ModelFile, set Features and then call DetectAndUpgradeFeatures to generate any necessary upgrade events.

  • [MODEL] AttributeSnapshot, EntitySnapshot, RelationshipSnapshot and SectionSnapshot now have a ToEvents method which emits events that can produce just that element of the model.

  • [ORM] Entity Props classes now implement IProps which provides easy access to all of the common properties.

  • [ORM] IEntity now includes a props property.

  • [ORM] Feature entity interfaces now include a props property that shadows the props property from IEntity.

  • [ORM] Each feature entity interfaces must also define a Props interface that the Entities template will automatically implement.

  • [WPF] Breaking: The audit feature and the application settings feature will no longer have "Prebuilt" screens generated, since they did not use any custom behaviour.

v280.3.0

  • [WPF] UseIntegratedLogin() is now compatible with SharedSecretAuthentication.

v280.2.2

  • [WEB] Bugfix: Reloading the browse page with no query string will now reset the criteria back to their original values - now actually works.

v280.2.1

  • [ORM] Bugfix: No context was ever considered equal to a non-core IEntityContext.
  • [WEB] Bugfix: Reloading the browse page with no query string will now reset the criteria back to their original values
  • [WEB] Bugfix: Criterion combinator .Default() was ignored if followed by .VisibleIf(), HiddenIf() or Rename().

v280.2.0

  • [WEB] <CommandBar> error messages are now appropriately sized for IsSmall bars.
  • [WEB] Criteria reset commands now reapply customised defaults.
  • [WEB] Reloading the browse page with no query string will now reset the criteria back to their original values
  • [WPF] TabbedShell constructors which do in-shell autoupdates now take the same optional arguments as other HTTP-based apis.

v280.1.0

  • [WEB] EntitySearchView component now has a Reset() method which resets the criteria back to their original (default) values

v280.0.0

  • The.Extension projects are now Instagile.Extension.
  • Removed the "Instagile 2015" extension which supported old Visual Studio versions.
  • [SQL] SQLEntityStore can now detect version conflicts when two separate transactions attempt to set the initial value of a reference (1:m) relationship. Previously this would be a unique key violation, producing a generalised WriteFailureException; now it's a proper VersionConflictException with the usual structured details.
  • [WEB] When commands lead to version conflicts, the conflict details are now reported in the notification details.

v279.7.2

  • [WEB] Setting the property value (via code) on ListReferenceField to an entity that does not exist in the options list, will now automatically add it to the options list

v279.7.1

  • [ORM] Added SingletonEntityInitialiser, a specialised CreatingEntityInitialiser which will initialise an entity with a specific ID instead of a new one.
  • [WEB] Fix error refreshing Browse page with default criterion after changing any criteria value.
  • [WPF] Sorting by collections in scrolling lists generated subtly-incorrect LINQ - calling IEnumerable.Count() on an IQueryable. This does not work in the new more-rigorous query translator, and has been fixed.

v279.7.0

  • [LICENSING] Added a new license option, -d/--demo. If supplied, the granted license will run in non-production mode if the grant conditions aren't met - it's up to the application how to interpret this and enforce licensing.

v279.6.0

  • [ORM] Added AttributeBase.DynamicTypeDefault which returns an attribute's TypeDefault as an object.
  • [WEB] Clear all validation triggers on other commands when executing a command
  • [WEB] Validation notification severity now matches the validation result severity

v279.5.1

  • [SQL] Fixed treatment of multiple orderings (order by e.X, f.Y, .OrderBy().ThenBy()). These were stored in a hashset - that is, the orderings were unordered - which happened to work most of the time because HashSet<T> accidentally preserves insertion order until you remove something!
  • [SQL] Simple queries which use .OrderBy() without Skip() or Take() no longer generate a subquery. This needless subquery was working around the problem above by accident - when generating a CTE and a CIndex column, it coincidentally avoided mutating the 'set' and was able to treat it as a list.
  • [SQL] Added heuristics for when to use subqueries with set operators - basically, if you're selecting an entire entity, the correlated subqueries used to load its relationships are costly enough that they shouldn't be duplicated for each side of the UNION ALL, whereas if you're only selecting a subset of column values it's more important to avoid the outer join that a subquery requires.

v279.5.0

  • [SQL] Removed a redundant join when inner queries were based on collections-of-references.

  • [SQL] Support for inner queries which reference components of the outer query from arbitrary clauses. Queries like this now work:

    from f in Farm.Query(ctx) 
    where f.Birds.Where(a `=>` a.Wingspan `>` f.Value).Any()
    select f;
    
  • [SQL] Fixed queries which contain multiple inner queries with overlapping join paths, like this one:

    from t in Narcissistree.Query(ctx)
    where t.Children.Any(n `=>` n.Parent != null || n.Parent.NodeData != null)
    where t.EldestSibling.Children.Any(n `=>` n.Parent != null && n.Parent.NodeData != null))
    

    This used to work because .Any() was a special case that built an id-list and generated an IN condition. Now it works because we correctly implement isolated mutual scope.

  • [SQL] Reduced the sheer volume of text in entity projections by adding aliases.

v279.4.0

  • [SQL] Aggregation operators no longer generate needless ordering and uniquing - no more SELECT DISTINCT COUNT(DISTINCT x).

  • [SQL] Set operators have a more rigorous treatment of inner or outer Distinct() and should combine properly with it in any position.

  • [SQL] Improved translation for inner queries, eliminating a redundant join.

  • [SQL] Support for inner queries on indirectly related entities reached via properties, like so:

    Entity.Query().Where(e `=>` e.Foo.Bar.Baz.Count())
    
  • [SQL] .Any() inside a .Where() now translates as an inner query, with full support for all operators.

  • [SQL] .All() is now translateable inside .Where() too, with efficient output for nonpresence testing. Like other inner queries it can be combined with skip/take/select/whatever.

v279.3.0

  • [WEB] Added support for warning validations

v279.2.2

  • Fixed packaging problems in Instagile.Web.Frontend - first-checkout clean builds without an IDE open didn't include the static web assets necessary to run Blazor apps.

  • [ORM] Information about the timing and call hierarchy of the following is now recorded when saving, if Debug logging is enabled for The.Persistence.Write.SavePlanner:

    • Attribute calculations
    • Entity OnSaving and OnSavingAsync
    • Relationship lazy loads

v279.2.1

  • [SQL] Fixed selecting columns from ordered, filtered collections. Broken queries had this form:

    Farm.Query(ctx).SelectMany(f `=>` f.Cats).Where(x `=>` x.Name != "").OrderBy(x `=>` x.Utterance).Select(x `=>` x.Text)
    
  • [SQL] Fixed ORDER BY output for T-SQL - when the ordering column is not in the select list, it must sometimes be added.

  • [SQL] Reduced nesting in query translation - .Select() and .SelectMany() used to generate a subquery whenever Distinct() was in use. Now they only have to do it when windowing.

v279.2.0

  • [SQL] Added support for outer range variables in .Any():

    Foo.Query().Where(f `=>` f.Bars.Any(b `=>` b.X == f.Y))
    
  • [SQL] Added support for windowing (.OrderBy(), .Skip()) of concatenations (set operator call sequences). You can now write queries like:

    Human.Query(ctx).Where(h `=>` h.Name == "Macbeth").Concat(Human.Query(ctx).Where(h `=>` h.Name == "Duncan")).OrderBy(h `=>` h.Age)
    

v279.1.0

  • [ORM] Recalculator recalculates attributes for an entity batch one at a time. It would previously recalculate all of one entity's attributes, then the next entity's, and so on; it will now recalculate one attribute on all of the entities, then the next attribute, and so on. This allows lazy load reporting to include the name of the attribute that triggered the lazy loads.
  • [ORM] Recalculator now loads all collections defined as calculation dependencies, not just many-to-many collections.
  • [SQL] Projected aggregate queries (like .Sum(e => e.Column)) now work again. They're a lot more efficient than before, as they no longer require subqueries or outer joins.
  • [SQL] Query translation no longer generates GROUP BY clauses. These were originally necessary to work around a lack of proper scope handling, which we now have; DML still supports grouping, so we can use it in future to implement it other features.
  • [SQL] Improved support for null checks within aggregate reifications (like .Sum(e => e.Foo == null ? 0 : 1)). This already worked in Sqlite, but not T-SQL. We now have a translation policy mechanism which allows generating different structures based on database features.
  • [WEB] Fixed blazor frontend assets packaging.

v279.0.0

  • Building the framework now requires .NET 7.0.

  • [ORM] Breaking: PersistenceService methods (and some of their callers) which take an IEntityContext? or IPrincipal? now take IEntityContext or IPrincipal - nulls are no longer permitted. Supplying null used to result in a call to SecurityService.CreatePrincipal(), using the ambient identity, which could have surprising results.

  • [ORM] ModelAudit can now be configured to include or exclude feature properties from auditing (previously it would always exclude feature properties).

  • [ORM] ModelAudit can now be configured to exclude a specific entity type or property from generating a specific audit violation by adding to EntityExclusions or PropertyExclusions respectively.

  • [ORM] Bugfix: ModelAudit would not exclude entities added to ExcludedEntityNames from generating model audit violations.

  • [ORM] More NRTs.

  • [SQL] Breaking: Fixed spelling of threshold in a number of places.

  • [SQL] Query translator architectural improvements, encapsulating the difference between relational algebra operators and actual SQL statements in a two-stage AST. Backends are now simpler, with more common code, reducing the difficulty of supporting extra RDBMSes. There are also some app-facing benefits, including:

    • Support for .Any() and All() on nested input relations - for example, this query now works: Foo.Query(ctx).OrderBy(b => b.Name).Skip(1).AnyAsync(b => b.Name == "foo").
    • Generalised support for treating entities as single values - something like Entity.Query().Where(x => x == x) now works.
    • Generalised support for aggregating sub-queries. Collections accessed in lambdas now support all the query operators - this means queries like Foo.Query(ctx).Where(f => f.Bars.Skip(1).Count() < 4).Select(f => f.Bazzes.Select(g => g.X).Sum()).
    • Support for the standard set operators - Concat(), Union(), Intersect() and Except(). These can be combined with each other and existing operators.
    • Support for bool-valued elements of projections in subsequent filters. You can now write .Select(e => e.SomeBool).Where(b => b && true).
    • Comparing columns to null no longer requires an inefficient OUTER JOIN.
    • Comparing references to null is much more efficient - in common cases, it can use a WHERE EXISTS on the foreign key instead of multiple LEFT JOINs.
    • Referencing multiple columns from the same table no longer generates redundant joins.
    • Reduced unnecessary use of common table expressions.
    • In SQL Server, join tables and joined entity tables are consistently referenced with a schema prefix (by default, dbo).
  • [TEST] Added XMLAssert to Instagile.Xunit, with utility methods for comparing XML.

  • [WEB] StartupJobs can now be used as StartupRequirements (via an AddStartupRequirement() overload), which makes it easy to delay presentation of the frontend UI until migration and other bootstrapping tasks are complete.

  • [WEB] Added OnLoaded event callback to The.Blazor.Pages.Edit component.

  • [WEB] NullableIntegerField component and NumberTraitsBox widget now both implement MaxLength property

  • [WEB] Bugfix: Race condition meant criteria was being applied before async criterion defaults were set.

  • [WPF] Breaking: Fixed spelling of threshold in a number of places.

  • [WPF] LoginScreen bugfix: entering a blank password for a user you'd already logged in as in the current session would reestablish the existing session, despite the missing password, as long as it was within the server's 5-minute key expiry window. This could let someone log in as the previous user on a shared computer if they signed out and walked away.

v278.2.0

  • [IMPORT] ImportService.CalculatePropertiesAsync() was affected by the query translation issue above. When recalculating entities with non-default sort orders and calculated properties dependent upon many-to-many relationships, in order to preload data, it generated queries to load pairs of IDs representing a relationship using the pattern above and threw an SqlException. This is fixed.

  • [SQL] Query translation now supports picking values from a query's source entity after cardinality reduction operators - skip/take/distinct - followed by reprojection. In other words, queries like this one:

    Entity.Query().OrderBy(e `=>` e.ModifiedOn).Take(10).SelectMany(e `=>` e.Relationship, (x, y) `=>` new { x.Foo, y.Bar })
    

    Previously, this didn't work because the 'x.Foo' was translated as a reference back to the original table, which was no longer in scope.

v278.1.0

  • [MODEL] Templates can now be configured with arbitrary app-specific code. TemplateBase has a new Options property, which allows you to resolve instances of ITemplateOptions defined with no-argument constructors by templates and further-subclassed in a Model/Generated/GenOnly location.
  • [ORM] Diagram-generating templates have moved to The.Management.
  • [ORM] Added two new templates in The.Management: ModelListing, which generates a .txt file describing the app model for documentation purposes, and ModelAudit, which applies configurable rules to validate what's in the app model. ModelAudit rules can be customised by defining a subclass of ModelAuditOptions; currently none of them are on by default, but we will set sensible defaults at some point.
  • [TEST] Added The.Xunit.AssertingLogger, a MEL logger which, when disposed, will turn logged errors into test failures. The log level to treat as an error can be configured, and a regex filter can be set to match only specific log entries.

v278.0.2

  • [WEB] "Reset Search" command button won't appear more than once on EntityCriteriaView after re-render causes OnParameterSet to run again

v278.0.1

  • [WEB] JobBase now has separate parameters for:

    * "user", the principal the job runs as and uses the permissions of, and
    * "startedBy", the identity of the user who started the job
    
  • [WEB] Bugfix: JobBase did not record its current status to the JobRun entity.

v278.0.0

  • [ORM] InvalidRegistrationException now reports the type of the invalid plugin.

  • [WEB] Tweaked endpoint/status text.

  • [WEB] .AddTheUpdates() now available in Instagile.Web.Backend, for using UpdateController without The.Web.IServices.

  • [WEB] Similarly, .AddTheEndpoint() is no longer required in simple cases. An endpoint using standard config will be added by default.

  • [WEB] Some steps toward unified, declarative jobs:

    * StartupJobs and ScheduledJobs are now both subclasses of JobBase.
    * Added ManualJobBase.
    * All jobs can now record progress (although for MigrationJob it's turned off by default, since you may not have anywhere to record to).
    * All jobs can now be executed manually, and their current execution status can be monitored.	
    * AddJob() registers the job *as* a job, as well as an IHostedService, making it available for inspection. It is necessary to use AddJob instead of AddSingleton/AddTypedHostedService/etc, unless you really really don't want to.
    * Added a first cut of `<JobControlView />` in Instagile.Web.Frontend.
    
  • [WPF] EntitySelectorModel has a new ResetCanSearch method which hides the magnifying glass button if it's visible.

  • [WPF] When a LookupInlineReferenceField is bound to an entity and its context is saved, the field will change modes to appear as though the containing screen was refreshed.

v277.1.0

  • [MODEL] The model editor's attribute-type dropdown now provides a way to set CalculationType.Manual, for attributes that should only be updated periodically or explicitly.
  • [SQL] Replaced SQLEntityStore's optional constructor parameters with a delegate Action configure.
  • [WPF] CreateController.SaveAsync now returns the DisplayController it creates to replace itself or null if the save fails.

v277.0.0

  • [ORM] Breaking: Removed the public constructor of The.Composition.Root. It has become increasingly infeasible to construct Roots correctly by hand - please use The.Composition.Builder instead.

  • [RPC] LocalEndpoint now verifies that the client's version and environment are the same as that of the server. Options.RPC.EnforceVersionMatch = false can be used to disable this. The verification will happen on every nonanonymous message, so if a server update occurs existing clients will stop working.

    Note that this is a breaking change for integration tests - anything that creates an IServices and an RPCClient will need to line up their versions correctly.

  • [SEC] New licensing option: challenge-response requirements. A challenge can be used alone or combined with model hashing, expiry dates, etc. There are two types of challenge: cryptographic signatures, represented as chunks of base64, or short PINs like 01-2345-6789. The PIN are not secure against cracking, but can provide an extra layer of protection while being easy to convey in speech or text.

    • The.Tool licence -c <pin|sig> generates a license file with a challenge requirement.
    • New command The.Tool respond <pin|sig> <challenge> creates a response that the application can verify.
    • LicenseService.CheckStatus(string? challengeResponse) can be used to check whether a response is valid before committing it to some datastore.
  • [SEC] Licensing namespace now has NRTs.

  • [SEC] Breaking: fixed misspelled licensing config methods in Instagile.Web.

  • [SQL] Bugfix: Ordering a query by some nullable attribute's HasValue member would throw an exception.

  • [WEB] Unbreaking change: EntityFieldBase subclasses no longer have to override the new validation hooks.

  • [WPF] Added a string overload of SimpleHttpClientFactory.WithBaseAddress(). (The same API already exists for the non-WPF version.)

v276.0.0

  • [ORM] Bugfix: the MemoryPersistence template would generate code that produced nullable warnings when using the data scrambling model feature.
  • [ORM] Breaking: EntityMetadataDictionary now has one Dictionary<string, IEntityInfo> constructor parameter instead of an ever growing list of IEntityInfo? parameters.
  • [ORM] Breaking: WellKnownFeatures.All has been replaced with FeatureCollection.WellKnown as a step towards application defined features.
  • [ORM] Breaking: IFeature has changed to allow for feature entities to support multiple interfaces, such as IScrambledDatabase and IScrambled.
  • [ORM] TemplateBase has a new Features property which templates can use to inspect all currently available model features, instead of directly referring to WellKnownFeatures.
  • [WEB] When <CommandBar> executes a command, it will clear existing notifications so that they don't stack up unhelpfully.

v275.0.1

  • [WEB] Tweaked <CommandBar> appearance, particularly when it's centered vertically and there is exactly one or zero notifications.

v275.0.0

  • [ORM] Breaking: NotificationSeverity has moved from The.WPF.Shell to The.Logging.
  • [WEB] Breaking: Split out most of <ExceptionView> into The.Blazor.Controls.<NotificationView>, which can be used to display messages with optional details of varying severity. <ExceptionView> still exists as a wrapper.
  • [WEB] Breaking: Added IProgressHost.ShowNotification() for commands to present messages other than errors.
  • [WEB] Breaking: <CommandButtons> has been replaced with <CommandBar>. This new component is a single block-level element rather than a set of inlines. It handles potentially-multiple notifications and failures from a command - validation warnings, info/success messages, deliberate errors, throws, etc.
  • [WEB] Bugfix: Progress recorded by a job would still sometimes be missing a linebreak.
  • [WEB] Added new theme colours: --the-warning-background, --the-information-background, --the-success-background and associated -border versions.
  • [WPF] Breaking: Generated criteria factories' overrideable methods now have a return type of ICriterion<T> instead of Criterion<T>, so criterion combinators can now be used within these methods.
  • [WPF] There is a new WithSubcriterion criterion combinator, which adds an additional subcriterion to the criterion.
  • [WPF] Breaking: ICriteriaFactory<T, TSpec> now has Surface and Metadata properties.

v274.0.1

  • [WEB] <CascadingUserAccount> now renders ChildContent immediately (with a not-logged-in null user) so that shells or applications can provide their own placeholders.

v274.0.0

  • [ORM] To ease the transition to asynchronous I/O, bool Options.DisableSyncReads has been replaced with enum Options.SyncReads. It has three options: Enabled (like the old false), Error (like the old true) and Warning. If SyncReads is set to SyncIOMode.Warning, lazy loads will succeed but log.
  • [WEB] <BoundFunction> and <BoundTask> have a new public method, Reload(), which will initiate a rebind regardless of parameters and @key. <BoundTask> also has also gained a property, IsLoading, which will be true while (and only while) the component is awaiting its binding. It doesn't re-display its initial loading placeholder, so this property can be used if you want to orchestrate a placeholder externally.
  • [WEB] The <Browse> page is now cancellable - meaning that if you navigate away while GetAllAsync() is running, the query will end.

v273.2.0

  • Bugfix: The.Tool's generate command now correctly identifies templates in Instagile.dll.
  • [MODEL] Added commands to reorder properties within sections.
  • [MODEL] Fixed the "double click to jump" functionality, which broke at some point.
  • [MODEL] Fixed crashes when dragging properties/sections, and improved reliability of section dragging.
  • [ORM] SequentialWriteOneReadManyDocumentStore is a new variant of WriteOneReadManyDocumentStore that calls each store in sequence instead of calling them all at the same time.
  • [ORM] Component interfaces are now correctly annotated for nullable reference types.
  • [ORM] Bugfix: UserAccount.Username was missing from the UserAccount feature's known columns list.
  • [ORM] ComponentService.GetUserAccountAsync() now preloads reference relationships on the account to improve startup time of shells.
  • [WEB] Bugfix: Progress recorded by a job would sometimes be missing a linebreak.
  • [WEB] "Bugfix": BlobDocumentStore would pass non-ASCII characters through to BlobServiceClient, which is too stupid to escape them. Documents' creator and original filename will now be URL-encoded to work around this.
  • [WEB] QueryState error logging no longer enumerates the whole query synchronously.
  • [WEB] <Browse> supplies a unique per-type key to QueryState so that you can have more than one Browse page on a... page.

v273.1.1

  • [WPF] Bugfix: Criteria for non-nullable boolean attributes did not work correctly when nullability was not enforced in the model; "yes" and "no" did not match all available entities between them.

v273.1.0

  • [RPC] Cancellation exceptions are no longer converted to RPCExceptions (similar to the earlier ORM change).
  • [SEC] Plugin callbacks now propagate custom authentication failures. What this means in practice is that if some IFooStore implementation tries to use persistence or RPC and fails due to a weird login state, the ensuing SecurityException will report that state instead of a generic NotLoggedIn.
  • [WEB] WebAuthentication and BlazorAuthentication now handle the auto-logout that occurs when sessions using Windows Authentication disconnect from IIS.
  • [WEB] <ErrorChrome> and <DebugChrome> are now 100% width of their containing block, to better serve as placeholders.
  • [WEB] Added <ErrorSpan>, which is to <ErrorChrome> as <DebugSpan> is to <DebugChrome>.
  • [WEB] <RowDocument> now supports cancellation, error display and other field-style loading features.
  • [WEB] <RowDocument> can now be given a custom Principal to load as a non-ambient user. Entity-based data will load in the entity's context, but documents don't necessarily have a context. This can be important when prerendering - you may have a principal derived from an identity that can no longer be ambiently reestablished.

v273.0.0

  • [ORM] EntityFactory has a new ReifyGraph method which reifies entity and pair batches, using the latter to eager-load collections, and returns the entities it reified.

  • [ORM] Breaking: EntityExtensions.ReifyRelationshipPairs has been removed; use ReifyGraph instead.

  • [RPC] We had three different ways of specifying "HTTP config and a web address" in WebEndpoint, AutoUpdater and UseIntegratedLogin. The last two (from Instagile.WPF) were particularly egregious because they both configure an AutoUpdater. This was a source of bugs.

    All framework APIs which require http config now work the same way as WebEndpoint; they have a set of overloads or parameters with an optional factory and an optional address. If no factory is provided, the API will use SimpleHttpClientFactory without a base address, so the application will have to provided an absolute address. If a factory with a base address is provided (by ASP.NET Core injection, or SimpleHttpClientFactory.WithBaseAddress()), the calling application can provide a relative address or none at all (in which case each API will use its default).

  • [WEB] Bugfix: Obfuscation was breaking injected EntityState in release mode.

  • [WPF] Breaking: The meaning of the arguments passed to AutoUpdater and UseIntegratedLogin have changed. There's no separate controllerPath, and instead of a optional base address, you must optionally supply either an absolute address to the update controller or, if the http client factory has a base address, an relative address to override the default controller path. In short, it now works the same way as WebEndpoint.

    Most applications should use SimpleHttpClientFactory.WithBaseAddress("http://myapp.azurewebsites.net/") and avoid setting the address parameter at all.

v272.0.0

  • Another package has been renamed:

    • The.WPF -> Instagile.WPF
  • [ORM] Initial support for System.Text.Json in a few types - Row and ColumnsByIndex. Full support will have to wait for .NET 7, when support for polymorphism was introduced.

  • [ORM] Added method EntityFactory.Petrify(). This is the opposite of Reify() - it turns a kernel into a row, instead of a row into a kernel - and has the same overloads.

  • [ORM] Added EntityReferenceProperty<T>.AsLoaded(), which asserts that the reference is already loaded and returns its current value if so.

  • [TEST] Breaking: Removed The.Xunit.STAFact - we are now using [WpfFact] from the open-source https://github.com/AArnott/Xunit.StaFact

  • [WEB] <CascadingUserAccount> has moved from The.Blazor.Controls to The.Blazor.Shell. It now has error handling for the optional Init callback.

  • [WEB] Added a new abstraction for prerendering with reduced FOUCs. EntityState<T> can be injected into any component to persist a graph from the prerender to the live circuit via .NET 6's <persist-component-state />; QueryState<T> does the same thing for non-loaded entity sets. Pages (<Edit>, <Browse>, <Reminder>) and <CascadingUserAccount> have built-in support.

  • [WPF] Breaking: Because the assembly name has changed from The.WPF.dll to Instagile.WPF.dll, all XAML references to the assembly must be changed. For example, a namespace attribute...

    xmlns:the="clr-namespace:The.WPF.Controls;assembly=The.WPF"
    

    ...would be replaced by: xmlns:the="clr-namespace:The.WPF.Controls;assembly=Instagile.WPF" A resource dictionary referencing some BAML...

      <ResourceDictionary Source="pack://application:,,,/The.WPF;component/Themes/Inky.xaml" />
    

    ...would be replaced by:

      <ResourceDictionary Source="pack://application:,,,/Instagile.WPF;component/Themes/Inky.xaml" />
    
  • [WPF] Bugfix: Grid screen was performing a needless sync load. It does need to load the whole set (unlike List screens) but it can at least be done asynchronously.

v271.2.1

  • [ORM] Cancellation exceptions are no longer converted to ReadFailure and WriteFailure exceptions, so that they can be handled as cancellations by higher layers of the stack.
  • [SQL] SqlExceptions representing cancellation are now converted to OperationCanceledExceptions.
  • [WEB] <EntityBox>, and the generated criteria which use it, now have a <has no value> option to search by null relationships. You can set AllowNulls=false to remove this option.

v271.2.0

  • [RPC] EndpointControllerBase now handles client-disconnect cancellations (which are surprisingly common) internally and does not pointlessly log "errors".
  • [RPC] LocalEndpoint passes through cancellations rather than converting them to miscellaneous errors.
  • [WEB] Added <LoadingPlaceholder>, which is used as the default LoadingContent in various places which used to just display text; it has a CSS class that you can target to theme dynamic unloaded content.
  • [WEB] <CascadingUserAccount> now cascades a UserAccount? entity instead of a Task<UserAccount> The entity's value will be null if it hasn't been loaded yet. It also has a new optional parameter, EventCallback<UserAccount> Init, to set up an account exactly once.

v271.1.0

  • [ORM] LoadGraphAsync's CancellationToken parameter is now nullable which brings it in line with other methods in the framework that trigger persistence operations.
  • [WEB] SelectionContext now has 2 new methods: AddRange and Clear

v271.0.0

  • Some more packages have been renamed:

    • The.Model -> Instagile.Model
    • The.Model.WebEditor -> Instagile.Model.Web
    • The.Model.WPFEditor -> Instagile.Model.WPFEditor
  • [MODEL] Namespace changes:

    • The.Model.WebEditor -> The.Model.Web
    • The.Model.WPFEditor -> The.Model.WPF
  • [MODEL] There is a new Job Status model feature which provides a place for job runs to be recorded.

  • [SQL] Optimisation: query translation will no longer produce LEFT OUTER JOINs in order to implement a reference null check if a property of the null-checked reference is also checked in some other way - an INNER JOIN serves same purpose. What this means in practice is that the following pattern generates reasonable DML:

    .Where(x `=>` x.Foo != null && x.Foo.Bar `>` 3)
    
  • [WEB] Breaking: ScheduledJobBase has undergone some changes:

    • Job runs are now recorded if the IsJobRunRecordingEnabled property is set to true and the Job Status model feature is enabled.
    • Jobs can now report progress using ExecuteOnceAsync's new progress parameter. If job run recording is enabled, this is persisted to a JobRun entity regularly (controlled by the JobRunProgressUpdateInterval property) and when the run completes.
    • Scoped services and a trusted principal are also passed into ExecuteOnceAsync so jobs do not have to create them.
    • Override the Name property to change the identity of the trusted principal.
  • [WEB] TimeOfWeek now has a TryParse method and a TypeConverter, meaning that a JSON value like { "DayOfWeek": "Monday", "TimeOfDay": "01:00:00" } can now be replaced with the string "Monday 01:00:00".

v270.0.4

  • [ORM] Annotation improvement: .Include() no longer expects a non-nullable entity reference.
  • [ORM] Annotation improvement: non-nullable properties of types String, Text and BLOB - to which it is safe to assign null, because the framework will replace it with a default - are now [AllowNull].
  • [WPF] Bugfix: the Controllers and Models templates could generate nullable annotations in a nullable-disabled context, causing warnings. Their output now begins with #nullable enable annotations so the warnings should no longer be generated.

v270.0.3

  • [ORM] Namespace The.Linq now has nullable reference type annotations, which improves nullability analysis for ____OrDefaultAsync() methods.

v270.0.2

  • [ORM] EntityReferenceProperty.Get() and GetAsync() no longer allocate a Mutation or an async state machine when HasValue is false. If you want to both test and use a value, this pattern is recommended:

    if (await props.Foo.GetAsync() is Foo foo)
    {
      Use(foo.Bar);
    }
    

    It's efficient and plays nicely with NRTs.

v270.0.1

  • [WEB] BugFix: EntityListView no longer throws an exception when attempting to load included relationships for hybrid queries

v270.0.0

  • The.Model.WebEditor and The.Model.WPFEditor were on .NET 5, which is EOL. They now require .NET 6.

  • Some packages have been renamed:

    • The.Core -> Instagile
    • The.MSOffice -> Instagile.Office
    • The.SQLServer -> Instagile.SQLServer
    • The.SQLite -> Instagile.SQLite
    • The.Xunit -> Instagile.Xunit
  • [OFFICE] All types now have nullable reference type annotations.

  • [OFFICE] Namespace The.MSOffice is now The.Office.

  • [ORM] Several more namespaces have nullable reference type annotations, with various edge-case bugs fixed along the way. Notably, the code-generation templates now use NRTs, so entity classes will have properties of type Foo? for reference relationships and string? for nullable string attributes.

  • [ORM] Removed AttributeBase.IsEqualProperty, which has been obsolete since 2013.

  • [WEB] <RowDocument> now supports child content.

  • [WPF] Bugfix: generated GridRow types were needlessly loading data, synchronously, for collection cells.

v269.1.1

  • [ORM] Hidden relationships didn't previously include foreign keys or collection counts when an entity was loaded. Avoiding the counts is fine - they're potentially expensive and only useful for business logic - but the foreign keys are assumed to be present by other parts of the ORM, and this was causing various bugs, exacerbated by the fact that our test suite did load everything. Therefore:

    • SQLEntityStore and SQLiteEntityStore now load foreign keys for relationship sides with IsReference=true and IsNavigable=false
    • TransientEntityStore now correctly emulates non-navigability according to this new rule
    • Numerous weird behaviours are fixed - using hidden references could previously cause inconsistent field data, or trigger lazy loads, or fail to save.
  • [ORM] CancellationTokenSources are now disposed when feasible instead of relying on garbage collection. This will improve reliability if you're using CancellationToken.WaitHandle, but probably not otherwise (as that's the only thing to dispose).

  • [WPF] ListController will now preserve its surface's display context from the time it was bound to that surface when displaying entities modally. This makes the create and display behaviour of ListValueSectionedCollectionField consistent, as previously it would only use a display context when creating a new entity.

v269.1.0

  • [WPF] TabbedShell no longer provides access to top-level screen commands while a modal is open, to prevent the data loss bug fixed in 269.0.1. The command implementation will still error if you somehow make it that far.
  • [WPF] Added utility function Dispatcher.Yield(); call and await this if you want any enqueued actions or pushed frames to complete.

v269.0.1

  • [WEB] Command buttons with a IsVisibleAsync function defined now start in a not visible state.
  • [WPF] Bugfix: Create and Display screens would allow the user to save using the tab header or Ctrl+S even while a modal was open, potentially leading to data loss. This will now display an error instead.

v269.0.0

  • [WEB] Breaking: The.Web.Jobs.Schedule now allows scheduling a job to happen multiple times a day or at different times on different days. Existing appsettings.json files will cause an error at startup and need to be rewritten. Replace:

    {
        "Time": "01:00:00",
        "Days": ["Monday", "Tuesday", "Wednesday"]
    }
    

    with: { "TimesOfWeek": [ { "DayOfWeek": "Monday", "TimeOfDay": "01:00:00" }, { "DayOfWeek": "Tuesday", "TimeOfDay": "01:00:00" }, { "DayOfWeek": "Wednesday", "TimeOfDay": "01:00:00" }, ] }

  • [WEB] Bugfix: ScheduledJobBase would waste a bit of energy when rescheduled with the same schedule.

v268.0.0

  • [ORM] LoadGraphAsync now uses the new QueryPairs readop which is intended for populating many-to-many relationships.

    • Use the new EntityExtensions.GetGraphLoadOperations method to generate the readops that LoadGraphAsync would use
    • Use the new EntityExtensions.ReifyRelationshipPairs method to populate many-to-many relationships with the result of a QueryPairs readop
  • [ORM] Cancellation and tiemouts revamp: cancellation is now consistently optional in public apis, with the token's presence or nonpresence passed to low level apis like RPC. All RPC calls have a new global timeout (Options.RPC.Timeout) which will be used when no explicit token is specified. Higher level functions might impose a different policy - Save and Query use PersistenceTimeout instead, and Document rpcs default to not timing out at all.

  • [ORM] Bugfix: CSVWriter would miss any empty columns at the start of a row causing the whole row to be shifted to the left.

  • [WEB] Bugfix: Preloads on ColumnSpec are now working properly for in memory collections

v267.0.0

  • [ORM] Breaking: WebEndpoint now uses IHttpClientFactory. Web apps can customise the client by calling AddHttpClient(nameof(WebEndpoint), /* config */) on their service collection. For most WPF apps, replace:

    var server = new HttpClient() { BaseAddress = serverBaseAddress };
    // ...
    .RegisterEndpoint(new WebEndpoint(server, "endpoint/"))
    

    with: .RegisterEndpoint(new WebEndpoint(new Uri(serverBaseAddress, "endpoint/"))) or: .RegisterEndpoint(new WebEndpoint(SimpleHttpClientFactory.WithBaseAddress(serverBaseAddress), "endpoint/"))

  • [ORM] All RPCs used to time out after 100 seconds by default as a result of HttpClient's default timeout. The default for the WebEndpoint HttpClient has been removed so most RPCs will no longer time out; be sure to provide a CancellationToken when appropriate. Persistence RPCs will be affected by the new PersistenceTimeout option which defaults to 100 seconds.

  • [WPF] Breaking: AutoUpdater now uses IHttpClientFactory. For most apps, replace:

    var server = new HttpClient() { BaseAddress = serverBaseAddress };
    // ...
    .UseIntegratedLogin(/*...*/, server, /*...*/)
    

    with: .UseIntegratedLogin(/.../, serverBaseAddress, /.../) or: .UseIntegratedLogin(/.../, SimpleHttpClientFactory.WithBaseAddress(serverBaseAddress), /.../)

v266.8.0

  • [WEB] Command now has a VisibleWhen() method which controls when the conditions under which the command button should be visible

v266.7.0

  • [SQL] Bugfix: Selecting some types of values into a tuple would cause an error.
  • [WPF] Bugfix: LookupSectionedCollectionField would throw a NullReferenceException when adding an entity to its bound set if that set had no parent entity.
  • [WPF] Bugfix: ValueInlineReferenceField would clone but not relate the parent of the relationship into the create modal's context when creating a new entity.

v266.6.0

  • [WEB] FieldSpec now supports WithMaxLength() method. MaxLength implemented on StringField and TextField, defaults to the metadata value, but can be overridden using WithMaxLength()

v266.5.2

  • [WPF] Bugfix: ListControllers configured with CanOpen set to false would show a blank description column.

v266.5.0

  • [ORM] There is a new DisableAuthorisationCache framework option. This can have a significant performance cost but makes it much easier to debug authorisation.

  • [WPF] There are two new integrated login options that affect commands on the User Account display screen:

    • UsingPasswordAuthentication generates commands for controlling users' password login (defaults to true if PasswordAuthentication is being used to log into the current application)
    • UsingWebAuthentication generates commands for controlling users' ASP.NET Core login

v266.4.1

  • [WEB] Radio buttons now stack vertically instead of horizontally (as they did before validation changes accidentally changed this)

v266.4.0

  • [ORM] Added FailValidationRule, which is a validation rule that will fail if the condition on the validation scope is met (useful for entity level validations)
  • [ORM] Added Invalid() method to ValidationRules for creating FailValidationRules
  • [WPF] Added SectionModalController, which complements FieldModalController to allow for simple application-specific modals to be built around a section of fields.
  • [WPF] A new section combinator AsHero has been added, which causes the section to be a "hero" section. Hero sections appear at the bottom of Content screens, filling the screen width, rather than in the ColumnsPanel with other sections. Multiple hero sections are stacked vertically in relative display order.

v266.3.1

  • [WEB] Fix bug causing Create page to not reload when changing entity type

v266.3.0

  • [WEB] Added the ability to use a custom component in a Section Header
  • [WEB] EndpointController's ConnectAsync method will now wait for migrations to be complete if the application is using MigrationJob. In client-server scenarios, this means that the client can rely on the server being started up when it tries to make RPC calls (e.g. reading or writing entities).
  • [WEB] New composition method AddJob(). Previously jobs were added with AddTypedHostedService, and you can still do that, but the overloads of AddJob provide convenient ways to configure it and may integrate better with upcoming job-control features.
  • [WPF] Wizards can now specify a custom label for the button that completes a wizard via IWizardHost.CompleteCommandName.

v266.2.1

  • [WEB] Minor fixes to new parameters functionality on FieldSpec including adding constructor to FieldParameter class

v266.2.0

  • [WEB] Added support to FieldSpecs for specifying parameters to be set on custom field components
  • [WPF] Generated content controllers no longer use FieldFactory to create LookupSectionedCollectionFields.

v266.1.0

  • [RPC] In the Instagile.Web versions of Builder, AddRPC() has been replaced with IServiceCollection.AddTheRPC(), which injects RPCs in a deferred fashion; this lets them use dependency injection like controllers and other ASP.NET Core features. You can still add non-injected implementations directly to the core builder using AddTheFramework() overloads.
  • [RPC] Added DI-friendly utility base classes for RPC implementations in The.Web.RPC.
  • [RPC] Added The.RPC.Unit, a zero-size type with one element.

v266.0.0

  • [ORM] Breaking: PropertyPath has been redesigned:

    • RelationshipPath is a linked list of relationships and is used for specifying entities to be loaded
    • PropertyPath consists of a RelationshipPath and an optional trailing attribute, and is used to point to families of "values" like a calculation dependency or the data needed to load a list column
    • Both of these types are validated to prevent disagreement between one property's type and its successor's parent
  • [WPF] The title of the Reminders sidebar can now be changed.

v265.4.0

  • [WEB] Added isVisible and isVisibleAsync parameters to Command constructor for conditional display of the command button

v265.3.2

  • [ORM] Bugfix: LoadGraphAsync could throw an exception when using TransientEntityStore that would not be thrown when using SqlEntityStore.

v265.3.1

  • [OFFICE] Added a new overload of ExcelSpreadsheet.CreateCellFormat which allows specifying separate styles for the four borders of a cell.

v265.2.0

  • [ORM] Added async versions of EntityCollectionProperty and IEntitySet manipulation methods including: AddAsync, AddRangeAsync, RemoveAsync, RemoveRangeAsync and ReplaceAllAsync.
  • [WPF] Added an optional "isEditable" parameter to ValueInlineReferenceField's constructor. Set this to false to open the related entity as read-only and prevent creating or deleting it. VIRF's immutability continues to be (incorrectly) unaffected by field combinators.

v265.1.0

  • [ORM] Added generic WithCondition method to ValidationScope to handle IEntity subtype in conditions
  • [ORM] Fixed issue with conditional validation scopes not refreshing validation if condition evaluation has changed

v265.0.1

  • [EXPORT] Exporting PropertyPaths now loads all entities and relationships necessary to get to the specified data. This can be slow - specify a ExportOptions.Preload function if you need to improve performance.

v265.0.0

  • [ORM] Added IValidatable and validation functionality in ValidationScope and ValidationContext
  • [ORM] Added HasValue property to Property primitives
  • [ORM] Added OrderDictionary which functions as a dictionary but uses the order that items where added when enumerating
  • [ORM] Added AsyncRule delegate for rules which evaluate asynchronously
  • [WEB] Added the ability to configure validation rules in FieldSpecs or within custom fields
  • [WEB] Fields now implement IValidatable and will validate according to the configured validation rules and will indicate when in an invalid state, displaying validation errors within a tooltip
  • [WEB] Added focus changed functionality to most field types and underlying widgets
  • [WEB] Added CanParse function to fields to indicate whether the field contains parseable data
  • [WEB] Added Key property to Commands to identify them within a validation context
  • [WEB] Fixed issue with Splat attributes not being merged properly in BoxInput widget
  • [WPF] Added CompositeField, a multi-field suitable for things like rows of checkboxes.
  • [WPF] Bugfix: The implementation of requiredness for relationship properties was incorrectly checking IsDefaulted instead of HasValue or Count.

v264.0.2

  • [ORM] SecureStore's permission-checking methods now log which permissions were missing when they raise a PermissionDenied error.

v264.0.1

  • [WPF] Breaking: Most of LookupSectionedCollectionField's constructor parameters have been replaced with a new LookupSectionedCollectionFieldOptions record.
  • [WPF] Breaking: Custom row commands in Grid screens are now hidden behind a hamburger menu - rather than a traditional dropdown, it can be toggled to show or hide the commands for a given row. To disable this, set GridOptions.UseHamburger to false.
  • [WPF] Bugfix: LookupInlineCollectionField's canCreate constructor parameter was incorrectly passed through to LookupSectionedCollectionField's canSearch constructor parameter.
  • [WPF] LSCF's Add command can now be suppressed with a new option.

v263.0.0

  • [WPF] Breaking: The list column customisation mechanism has been redesigned.

    • ListColumn is now a record with only properties and a ToString override.
    • The number of "frozen" (unaffected by horizontal scrolling) columns in a list can be controlled by setting ListModel.FrozenColumnCount.
    • The special "initial column" returned by ListController.CreateDescriptionColumn is now a standard ListColumn that uses the new features below.
    • A ListColumn can now be given a ColumnType of ReferenceLink and DoNavigate and DoNavigateInBackground commands to make it appear as links instead of text.
    • ListColumn.AllowReordering can be set to false to stop the column from being reordered relative to other columns.
    • ListColumn.AllowZeroWidth can be set to true to let the column be resized as small as desired.
  • [WPF] Bugfix: A scarier-than-intended error would be raised if GridController failed to create a row during its first load.

v262.0.1

  • [ORM] Bugfix: Data scrambling would incorrectly re-scramble base items that had already been scrambled in the correct sequence.

v262.0.0

  • [ORM] A descriptive exception will now be thrown when WebEndpoint receives an RPC message whose header is not the advertised length.
  • [ORM] Breaking: ImportService and Recalculator no longer have an EntityFactory constructor parameter.
  • [ORM] Recalculator can now reify many-to-many collections specified as calculation dependencies.

v261.0.0

  • [WPF] Simplified validation, allowing the display of ErrorBorders on fields which use EntitySelector or CollectionSelector.

v260.8.5

  • [ORM] Added EntityExtensions.LoadGraphAsync, an extension method on IEntity and IEnumerable<IEntity> for efficiently loading a graph of entities from one or more root entities.
  • [ORM] Added LoadedCollectionEnumerator, an IVisitor that can be used to access the enumerator on an EntityCollectionProperty<T> without knowing T.

v260.8.3

  • [ORM] The generated FooProps, Entities, and FooInfo classes are now partial. This allows application code to modify them, e.g. to implement interfaces.
  • [WPF] Bugfix: The Scrambled Database Name field did not have sufficient error handling when querying the available databases for scrambling.

v260.8.2

  • [WEB] Fixed issue with Tooltip component not being detached when Enabled is set to false

v260.8.1

  • [WEB] Fixed issue with Tooltip component being cutoff within parent dimensions
  • [WEB] Fixed issue with Tooltip component sometimes being attached more than once

v260.8.0

  • [WPF] Significantly boost the performance of large grids by removing LazyField wrapping which seems to be a legacy holdover from before the list/grid separation.

v260.7.0

  • [WEB] Added IsReadOnly parameter to InstantBox and TimeBox widgets
  • [WEB] Bugfix: IsReadonly implementation was missing on some fields: NullableIntegerField, NullableBooleanField, NullableCurrencyField, NullableDateTimeField, NullableDecimalField, NullableGuidField, NullableLongField, NullableTimeField, TimeField

v260.6.0

  • [WEB] Added OnValueChanged functionality to EditSpec, ValueFieldBase and ValueReferenceField

v260.5.0

  • [WPF] Bugfix: The "Delete saved credentials" command for PasswordLoginHandler was missing.
  • [WPF] Allow applications to explicitly specify a login handler including entirely custom login handlers.
  • [WPF] Allow applications to customise the model used by built-in login handlers.

v260.4.0

  • [WEB] EntityBox component can now optionally take a BaseQuery parameter (IQueryable<T>) which allows passing in a custom query.

    If no value is supplied, the default behaviour is the same of the current behaviour which is to retrieve all entities of type T.

v260.3.0

  • [ORM] Added IApplicationSettings, the interface for the ApplicationSettings model feature. This is actually a completely empty subinterface of IEntity - the idea is that applications will add their own properties to it. For now, the only way to get one is ComponentService.GetSettingsAsync(), which returns a singleton.
  • [WEB] Fixed a composition bug preventing RecalculationJob from running.

v260.2.0

  • [MODEL] Added data scrambling model feature. This feature allows for entity stores and spreadsheets in CSV format to be scrambled. This allows for something that resembles the original data to be removed from a secure environment.

  • [MODEL] Added commands to model, entity and attribute nodes in the model editor to configure data scrambling behaviour.

  • [ORM] Added data scrambling RPCs:

    • Using any of these RPCs requires the Admin security privilege.
    • To preserve server resources, only one data scrambling operation can occur at any one time.
    • CSV files can be scrambled out of the box so long as a document service is configured, and the precise scrambling behaviour can be adjusted on a per column basis.
    • Scrambling entity stores requires configuring the framework's ScramblingOptions so that it knows how to access legacy services for the original entity store, as well as legacy and non-legacy services for the scrambled entity store, the model file is also required.
    • It is possible to provide custom scrambling behaviour for an entity type by overriding its legacy entity and implementing ICustomScramblingBehaviour.
  • [ORM] Added a simple CSV writer utility class.

  • [WPF] Added data scrambling screen customisations including extensive tooltips to help with feature discovery.

  • [WPF] Added ReloadableField, a field that delegates to an inner field. The Reload method will recreate the inner field which can be used to change it after a content controller has been initialised e.g. to change its visibility, label, mutability or anything else.

v260.1.0

  • [WEB] CriterionSpec.Default() has a new overload accepting an async function, which can generate a default based on I/O.
  • [WEB] Tooltip component now has an Enabled property (defaults to true)

v260.0.5

  • [WEB] Bugfix: "Reset Search" button was not appearing on EntitySearchCriteria component when base query has been set

v260.0.4

  • [ORM] Bugfix: EntityMetadataDictionary was missing a constructor paremeter for the application settings entity.

v260.0.3

  • [WPF] Fixed copy to clipboard errors relating to Windows Clipboard User Service issue

v260.0.0

  • Breaking: Packages which required .NET 5 now require .NET 6 (this includes The.Core, The.WPF, The.MSOffice, The.SQLite and The.SQLServer).
  • [ORM] PKIAuthentication no longer requires Windows (net6.0-windows). The frontend is still based on Microsoft USB drivers, so CSPKeyProvider is still [SupportedOSPlatform("windows")], but the backend and DBKeyProvider support net6.0.
  • [SQL] Bugfix: Changing the audit flag on a non-transient entity with a relationship to a transient entity would incorrectly generate a SQL migration batch to change the triggers for its non-existent join table.

v259.0.0

  • [ORM] Added ChangeCurrentUserPassword RPC. This allows users to change their own password without needing to have write permission for user claims.
  • [WPF] The built-in Change Password command now uses the ChangeCurrentUserPassword RPC.
  • [WPF] Breaking: BuilderExtensions.SetUsernameAndPasswordAsync has been removed, replaced with PasswordAuthentication.ChangeCurrentUserPasswordAsync.
  • [WPF] Breaking: The usage of the setUsernameAndPasswordAsync parameter for ChangePasswordScreen has changed, the first string parameter for the function is now the current password rather than the current username.
  • [WPF] Bugfix: Attempting to export from a list backed by an entity collection property would produce an error.

v258.0.0

  • [ORM] IEntity is now IHasChanges. This is a convenience rather than a major update - EntityKernel already implemented this interface. It's also not a breaking change, thanks to DIMs.
  • [WEB] Breaking: FieldBase is now abstract; custom fields that were using FieldBase directly (rather than ValueFieldBase) should generally switch to PropertyFieldBase.
  • [WEB] Added work-in-progress EntityFieldBase and EntityFieldSpec, for fields that depend on zero or >1 properties. Presently only useful with adapters like EntityFieldBase.CreateBinding().

v257.1.0

  • [WEB] Added <EntityEditView>.Include and Exclude, which allow you to restrict an edit panel to only a subset of the entity's sections.

v257.0.0

  • [ORM] When automatically accepting user registration requests, if a user account with the same username exists, that user account will now have its claims overridden instead of always attempting to create a new user account.
  • [ORM] Breaking: UserRegistrationOptions.AutomaticallyAcceptRegistration is now a DateTime? AutomaticallyAcceptRegistrationUntil. Automatic user registration will only occur prior to the time specified. If the time specified is more than one day in the future, framework composition will throw an exception (except if a debugger is attached).
  • [WEB] Added virtual method DefaultEditSpec.DefineSection() which allows scaffolding overrides to intercept the model hierarchy at a new point.
  • [WPF] Exposed ConfirmController for application use, a simple confirmation modal that shows a string with confirm and cancel buttons.
  • [WPF] Manual user registration approvals will now also overwrite an existing account with the same username, but will ask for confirmation first.

v256.0.1

  • [WPF] Fixed "Manage columns" window breaking after "Reset column".
  • [WPF] Bugfix: Labelled field combinators would in fact remove the field label rather than adding it.

v256.0.0

  • [WEB] Prevent JSDisconnectedException being thrown by Tooltip component when refreshing the page
  • [WPF] MenuBuilder.AddScreenLink has a new overload which allows specifying a delegate to run on the controller after it's displayed.
  • [WPF] Added a new field combinator "Labelled" which enables the field label without changing it.
  • [WPF] Added user registration command to password login handler.
  • [WPF] Breaking: Removed IntegratedLoginOptions.UserRegistrationController which stopped being useful after v250.
  • [WPF] Bugfix: The help marker for field tooltips would appear offset from the field label if the field was larger then normal.
  • [WPF] WizardBase.Bind<T> now returns an IOwnedValue<T> rather than an IValue<T>, though the value will never actually be owned by any entity.

v255.4.0

  • [WEB] Adding ShowOnCreate parameter to Tooltip component.
  • [WEB] Correctly detaching tooltip from target on dispose of the Tooltip component

v255.3.0

  • [DOCUMENTS] Added a simple file-based store, FilesystemDocumentStore. This has the advantage and disadvantage that it stores files with their original metadata on disk; good for interoperability, bad for security.
  • [DOCUMENTS] FileMetadata and ImageMetadata are now compatible with System.Text.Json.
  • [WEB] Added a Delete button to <FileField> so that uploaded files can be removed or replaced.

v255.2.2

  • [WEB] Fixes for rendering issues that occur when changing the value of IsReadOnly parameter in a value field component

v255.2.1

  • [WEB] Replace the false promise of HarvestDependencies in Instagile.Web layer roots with specific addition of Options to DI

v255.2.0

  • [WEB] Add FocusChanged event callback to NullableIntegerField

v255.1.0

  • [WEB] Add FocusChanged event callback to StringField
  • [WEB] Add IsEnabled property to RowButton

v255.0.0

  • [RPC] Breaking: The various RPC* settings have been moved from Options to a new inner type RPCOptions RPC.
  • [RPC] Encryption of streams has been disabled by default as we have had early reports of potential data corruption. It can be reenabled with new flag Options.RPC.StreamEncryption.
  • [RPC] Added flag Options.RPC.StreamBuffering to force streams being sent to/from an endpoint to be fully copied into memory before sent/after received; this is off by default, but it's an escape hatch for client or endpoint code which can't handle forward-only streams.
  • [WEB] Breaking: Replaced ad-hoc arguments to AddTheEndpoint overloads with an optional RPCOptions which is used instead of the .Configure()d default.
  • [WEB] Added Options.RPC.SessionServerDeadline.

v254.4.1

  • [WPF] Bugfix: Using a search modal to add a value to a LSCF could lead to unsaved changes being lost in the outer context when the value is cloned back.

v254.4.0

  • [ORM] EntityReferenceProperty.GetAsync now optionally accepts a CancellationToken.

v254.3.0

  • [WEB] Added <LoadingTitleBar> component with additional padding div to better allow position of the 'Loading...' title bar

v254.2.1

  • [ORM] SixLabors.ImageSharp has been updated from v1.0.4 to v2.1.1.
  • [RPC] When using an AuthenticationProtocol that includes encrpytion, AttachedStream elements of an RPC request/response are now also encrypted. The implementation uses a block cipher, with en/deciphering on the fly as bytes are transferred.

v254.2.0

  • [DOCUMENTS] Added optional IPrincipal argument to DocumentService extension methods which were missing it - GetRotationAsync(), GetFlippedHorizontallyAsync(), GetFlippedVerticallyAsync(), GetThumbnailAsync().

v254.1.0

  • [WEB] <FieldRow> derives its height from a FieldSpec's Rows property. This is now a minimum - if the field defined by FieldSpec.Component has a higher intrinsic height, the field will grow vertically to fit.
  • [WEB] When <MultilineBox> is in a context with a fixed height (like a <FieldRow>) it will no longer be shrinkable to less than the height of its container.
  • [WEB] <SectionField> (a piece of chrome used for lists, value references, etc) can now size to a parent with height or min-height - previously it had to be explicit.
  • [WPF] Advanced search criteria for reference data now provide the 'matches' options (which open a subcriteria picker), along with the sea-of-checkboxes version that refdata gets by default.

v254.0.3

  • [ORM] Fixed an unmarked breaking change where IAuthorisation was given a new optional sync method; the method now has a default implementation.

v254.0.2

  • [WEB] Fixed issue with AddTheOverrides failing when abstract IEditSpec, IListSpec, ICriteriaSpec exist.

v254.0.1

  • [SQL] Bugfix: string.IsNullOrWhitespace() and string.IsNullOrEmpty() did not successfully generate SQL in queries (they threw an exception instead).
  • [WPF] Bugfix: Calculated or autonum attribute grid columns were editable.

v254.0.0

  • [WPF] Bugfix: Attempting to export data from grids would, in most cases, throw an exception.
  • [WPF] Breaking: GridColumn has a new IsEditable property. This defaults to true when created by the default implementation of GridController.CreateColumn. A column's field will be editable only when both the GridColumn and the containing GridModel are marked as editable.

v253.1.0

  • [MODEL] Bugfix: Runtimes supporting model version 9 require UseInstantForAudit, but it was incorrectly only added if upgrading to the latest model version.
  • [WEB] <CascadingUserAccount> now performs an asynchronous login, so that it can be used with Options.DisableSyncReads = true.

v253.0.0

  • Some common code from The.Web and The.Blazor has been extracted into a new shared package, Instagile.Web. Namespaces remain the same for now, but will be changed in stages. The sharing will also increase over time, and the number of packages may be reduced.
  • The.Blazor has been replaced by a new package, Instagile.Web.Frontend.
  • The.Web has been replaced by a new package, Instagile.Web.Backend.

v252.2.0

  • [DOCUMENTS] RemoteDocumentStore now uses streaming RPCs instead of buffers.
  • [ORM] Added Options.RPCLeeway (similar to VersionConflictLeeway, but for early renewal of encrypted sessions).
  • [ORM] Added a struct (Nullable<T>) version of .WhereNotNull().
  • [ORM] Added RPC type AttachedStream. RPC messages can include an AttachedStream (in the T and/or U of Procedure<T,U>), which will be sent forward-only without client or server buffering.
  • [ORM] Bugfix: The.RPC.AnonymousImplementation had an incorrect constructor parameter type.
  • [WEB] Simplified some AddTheScopedFramework() overloads which use RPC (these are mainly for WASM use, and used to hardcode RemoteEntityStore but can now hook into general RPC config).

v252.1.0

  • [ORM] New high-level batching API: IQueryable.Include(). The Include operator works like Select(), but instead of navigating to another table, it marks the specified relations for loading in the same batch. This has the same features as preloading - all queries are executed in a single server-roundtrip, and all relationships are connected up automatically except for M:N collections. An example:

    await Human.Query(context).Include(h `=>` h.Owns).Include(h `=>` h.Drives).FirstAsync()
    

    In a single entitystore operation, this query will load a Human along with its property (if any) and vehicles (if any). More-complex queries are permitted, such as multi-level includes and inclusions at different points in a Select() chain.

  • [ORM] New low-level batching API: The.Persistence.Read.BatchBuilder. This can be used to generate a batch of ReadOperations and process the corresponding ReadResult into a fully-connected context.

  • [ORM] Removed extension methods like PersistenceService.CountByQuery() which were just wrappers around single readops. They weren't useful outside the framework, because they require an expression tree - and if you have one of those, you can just execute it.

v252.0.1

  • [WEB] Work around an ASP.NET Core bug which caused static web assets to be dumped in wwwroot/.

v252.0.0

  • Most packages no longer support .NET Framework 4. Only The.Model retains a netstandard2.0 build, so that it can be used in Visual Studio extensions.

  • The.Blazor and The.Web now require .NET 6. Desktop packages require .NET 5.

  • [SQL] Query translation now supports multi-"from" range variables and three-argument SelectMany (to which they are lowered). This enables queries like:

    from f in Farm.Query()
    from c in f.Cats
    select new { f.Text, c.Name }
    

v251.2.2

  • [WEB] <MultilineBox> can no longer be resized horizontally, only vertically - this was an easy way to break layouts, and it also triggered a reflow bug in Chrome.

v251.2.1

  • [WEB] Added <TextField> parameter Rows - although we have an opinionated default, apps may want to override it for design purposes.

v251.2.0

  • [WEB] Like other entity views, <EntityEditView> now has a T:IEntity type parameter and a corresponding <DynamicEntityEditView> component which doesn't need it. The non-dynamic version has a new feature, optional contextualised ChildContent - if supplied, this will be displayed instead of the scrolling columns panel, supporting custom entity editors that still use the view's features (command buttons, reactivity, etc).

v251.1.0

  • [WEB] Added a new optional parameter to GridShell - ContentWidth. If specified, this fixes the width of the main content, centering it on the page and adjusting gutters/sidebars as necessary.

v251.0.0

  • [RPC] Remote procedure definitions have been split into "Procedure" stubs - names, types and security attributes - and "Implementation" instances which only need to be registered at the ultimate destination. This achieves a few things:

    • Custom RPCs can be implemented server-side without their dependencies needing to be available to the client in shared code.
    • EndpointControllerBase no longer requires IServices, only IEndpoint - it can be used as a pure proxy, allowing multiple-hop RPC calls.
    • Built-in RPCs can be inspected and optionally whitelisted without needing to make the implementation public.
    • The ConfigureServices() integrations in The.Blazor and The.Web now have access to RegisterEndpoint() (for passing calls along to another server) and AddRPC() (for implementing custom calls locally).
  • [RPC] Remote procedures now have a name instead of a numeric opcode - less efficient, but much better for logging. You don't need to explicitly specify a name when defining a procedure; by default it will be named after the function or static initializer that creates it. This code:

    namespace Foo.Common
    {
        static class Procs
        {
            `Procedure<int, string>` GetThing = new();
            `Procedure<string, int>` SetThing = new();
        }
    }
    

    will define two procedures named Foo.Common.GetThing and Foo.Common.SetThing.

  • [WEB] <ListReferenceField> and <ComboReferenceField> are now generic, with a type parameter T. This will be inferred if you're using them like <ListReferenceField Property="myEntity.props.SomeRelationship" />. The generic fields have improved performance, and are no longer subject to a bug preventing sorting by modelled properties (that is to say, properties which aren't in EntityKernel).

  • [WPF] Added an error notification when OnLogin or OnLogout delegates fail.

v250.2.4

  • [SEC] Performing an InsertRelationship or DeleteRelationship operation now only requires that the given context has permission to write to the parent entity of either side of the relationship, rather than the parent of the relationship side indicated by the operation.

v250.2.3

  • [WEB] Improved cancellation handling in <ComboBox>.

v250.2.2

  • [SQL] Fixed query translation bug when using RemoteEntityStore over SQLEntityStore.
  • [WPF] Improved cancellation handling in VirtualisedList.

v250.2.1

  • [ORM] Applications can now customise the automatic user account creation process of the RequestRegistration RPC.
  • [SQL] Query translation can now handle entity types which aren't named the same as their actual class.
  • [WPF] Fixed codesigning being always-on, even in projects without a cert file specified.

v250.2.0

  • Includes changes from v249.8 through v249.11.
  • [WPF] Fixed a race condition in ListController initialisation.
  • [WPF] Code signing now works for dotnet publish under .NET 6 WindowsDesktop, and for single-file apps. By default, the application's dll and the apphost (if any) are signed in the intermediate directory (obj/); this behaviour can be customised with the new SignedIntermediate item to add or remove signatures in obj/. The existing SignedAssembly can be used as before to sign additional dlls in bin/, and the new SignedOutput will sign files in bin/publish/.

v250.1.0

  • Includes changes from v249.7.
  • [SEC] CallbackEnvironment did not survive contact with the enemy. It's been upgraded from an Identity + utilities to an IPrincipal + utilities.
  • [SEC] LocalEndpoint, the RPC backend, now provides purpose-constructed principals via the environment. This allows RPCs to use contexts and therefore entities even on a server which does not otherwise have local authentication - enabling, for example, RemoteDocumentStore over EntityDocumentStore with PKIAuthentication.
  • [SEC] PKIAuthentication now produces the correct error if asked to sign data when not using an anonymous key provider.

v250.0.0

  • [DOCUMENTS] The image-manipulation utility code which used to live in The.WPF is now in The.Core. This includes thumbnail generation, rotation and uploading with autodetection of type/dimensions.

  • [DOCUMENTS] Added RemoteDocumentStore, which works by calling internal RPCs. If an IEndpoint is registered, RemoteDocumentStore will be used by default, and you don't have to call RegisterDocumentStore().

  • [DOCUMENTS] All store implementations now consistently return null when documents are not found (which is translated to a higher-level error by DocumentService).

  • [DOCUMENTS] Downloading document contents is now streamable. The SQL and Blob backends implement streaming from disk/network to a client-provided location without storing the whole document in memory.

  • [DOCUMENTS] Removed "convenience" methods like IDocument.GetOriginalFilenameAsync() - historically these were useful, but all they do now is call GetMetadataAsync() and throw away the rest of the metadata. It's a performance trap.

  • [EXPORT] Export (to CSV, excel, etc) is now cancellable.

  • [IMPORT] Recalculation is now cancellable, and uses persistence cancellation internally.

  • [ORM] Updated MessagePack-CSharp - we're now close to, but not on, the latest version (as the very latest has a bug). This improves serialisation performance and post-.NET5 compatibility. It won't have any effect on web apps, as they were already pulling in a higher version of the package through ASP.NET Core itself (Blazor Server uses it).

  • [ORM] The.Core now depends on ImageSharp, so that we can process images consistently across environments.

  • [ORM] The.Core no longer depends on Json.NET (Newtonsoft.Json). It's still used by The.WPF, but not required in command-line or web applications.

  • [ORM] Added nullable reference type annotations to many more types in The.Core.

  • [ORM] Added The.CallbackEnvironment, a struct passed to most 'plugin' operations (IEntityStore, IAuthorisation, etc). An callback environment provides the basic utilities to operations doing work on behalf of the framework - an identity, a logger and cancellation support.

  • [ORM] Now that we have SQLiteEntityStore, the original function of DataContractEntityStore - serialising entities to a local file for single-user applications - has become redundant. Its in-memory mode is useful in unit tests and special cases, however. DataContractEntityStore has been cut down and moved to The.Persistence.TransientEntityStore; its internals, which applications shouldn't generally need, are in the new namespace The.Persistence.Transient. The associated code-generation template has been renamed to MemoryPersistence - its generated proxy types are no longer "POCOs" and nor do they have DataContracts.

  • [ORM] Removed The.Persistence.Remote namespace; RemoteEntityStore is now in The.Persistence, and everything else has been generalised into The.RPC. If an IEndpoint is registered, RemoteEntityStore will be used by default, and you don't have to call RegisterEntityStore().

  • [ORM] Fixed THE-1591 deadlock between sync and async reads on the dispatcher - if a deadlock would have occur, one of the threads will now throw an exception and the other will proceed.

  • [ORM] All entity operations are now cancellable. Added overloads for SaveAsync(CancellationToken), GetByID(IEntityContext, Guid, CancellationToken), ToListAsync(CancellationToken), and many others.

  • [ORM] Added support for enum values in LINQ queries and other serialized objects.

  • [ORM] Added support for IReadOnlyList in LINQ queries and other serialized objects.

  • [RPC] The remoting system formerly used by RemoteEntityStore has been generalised, allowing the framework and applications to securely execute remote procedures. This release of remote procedure call functionality should be pretty solid internally, but the public API for applications to define their own procedures is a prototype, subject to change.

  • [RPC] IEndpoint and associated types now live in namespace The.RPC. An RPC 'endpoint' represents a destination with the ability to execute serialised operations; the primary implementations are LocalEndpoint, which executes them using an IServices, and WebEndpoint, which sends operations over HTTPS.

  • [RPC] Most applications will not consume IEndpoint directly. The next layer up is RPCClient, a stateful type containing an endpoint, authentication config and serialisation config. RPCClient has methods like Connect() and Execute(), which take a procedure and return a The.RPC.Response.

  • [RPC] Registering an endpoint in the framework builder will enable the high-level API: RPCService. Available as IServices.RPC, this type allows applications to look up registered procedures and execute them with a <TRequest, TResponse> style API.

  • [RPC] RPCs are cancellable, and cancellation propagates through procedure calls. However, transactional write operations will not quit and rollback in the case of 'accidental' cancellation - for example, if a network connection is lost after the server receives the write request. These operations are still cancellable if the caller specifies a non-None CancellationToken.

  • [RPC] Procedures are defined as records which subclass Procedure<T, U> or AnonymousProcedure<T, U>, with request and response types that have [MessagePackObject] or a [DataContract]. They can be stored in static members or registered as instances using Builder.AddRPC(). This part of the API has some known limitations, which will be lifted later.

  • [RPC] Limitation: Initially, the procedure type must be available on both the client and the server, which means it can't use much in the way of dependency injection.

  • [RPC] Limitation: All application-defined procedures must have a unique opcode, a non-negative integer. This means you have to write something like

    public static `DelegateProcedure<string, string>` Pluralise = new(0, (services, request, principal, ct) `=>` { /* XXX */ };
    

    Or: public class PluraliseProcedure() : Procedure<string, string>(1) { public override async Task<Response<string>> InvokeLocal(IServices services, string request, IPrincipal principal, CancellationToken ct) => { /* XXX */ } }

  • [RPC] Removed the JSON serialisation format. We still have an ISerializer abstraction, but in practice all applications should use SerializationFormat.MsgPack - we're only keeping the XML format around to grease the extensibility api, perhaps temporarily.

  • [SQL] Added Stream() and StreamAsync() methods, which allow you to map a query to a single System.IO.Stream and read it incrementally (so that it doesn't have to be stored in memory).

  • [SQL] IDatabase now supports cancellation - all the async methods take an optional CancellationToken parameter. Cancellation is implemented by all existing backends.

  • [WEB] Virtualised-scrolling lists now use cancellation, so that if you close a page or navigate away, slow page-loading database transactions are terminated.

  • [WEB] The tooltips in image fields & cells no longer load a full-sized image; they use the same 480x320 thumbnail as The.WPF's similar tooltips.

  • [WEB] Fields and widgets use cancellation when loading sets of entities (for example, in dropdowns and combo boxes).

  • [WEB] ASP.NET Identity support now uses cancellation, which can improve page-load performance when multiple layers of components and services try to authenticate.

  • [WEB] ProxyControllerBase is now EndpointControllerBase, supporting all client->server RPCs. The.Web.Proxy namespace has been removed in favour of The.Web.RPC.

  • [WEB] UserRegistration is now RPC-based, so the UserRegistrationControllerBase has been removed.

  • [WEB] The.Web.Composition.Options is now available in DI.

  • [WPF] Virtualised-scrolling lists now use cancellation, so that if you close a page or navigate away, slow page-loading database transactions are terminated.

  • [WPF] ImageField and FileField use cancellation - if you stop a download or replace an image, it will terminate streams and transactions.

  • [WPF] DisplayController uses cancellation for loads and refreshes (but not saves).

v249.14.2

  • Fixed build on MSBuild 17 by updating version of Nullable nupkg.
  • [WEB] Fixed <FieldGrid> layout in Chrome 106, which has rewritten table layout.

v249.12.0

  • [WEB] Added HelpText to FieldSpec, HelpText will show in a tooltip when hovering over a [?] next to the field label
  • [WEB] Added support for custom label component to FieldSpec

v249.11.0

  • [WEB] Ensured that string and text fields that are audited have special characters escaped when inserting json into Audit tables.

v249.10.0

  • Fixed issue with CellSpec.Rename() function not actually changing the label under certain circumstances

v249.9.0

  • [WEB] Fixed excessive whitespace in <DateRange>.
  • [WEB] Fixed the interaction of error borders with focus borders - now the colour correctly overrides the focus.
  • [WEB] Added utility functions to modify the classList of an ElementReference.

v249.8.0

  • [WPF] ListController.OpenAsync may now be overridden.

v249.7.4

  • Bugfix: Progress reporting from ExportAsync had a race condition leading to weird jumps.

v249.7.4

  • Bugfix: The very first page of an ExportService export did not perform preloading correctly.

v249.7.2

  • Added ExportParameters.Preload, a hook for loading extra relationships into each page of data.

v249.7.0

  • [EXPORT] ExportService now operates on pages of exportable data instead of trying to load the whole output into a single IEntityContext. The API has changed, using a query factory and a parameter structure instead of all the overloads it used to have.

    Calls like: await Services.Export.ExportAsync(Human.Query(Services.CreateContext()), new CSVExportFormat(), outputFile, Human.Metadata.Drives); await Services.Export.ExportAsync(existingQuery, new CSVExportFormat(), outputFile, Human.Metadata.Drives); Now become: await Services.Export.ExportAsync(Human.Query, new(outputFile, Human.Metadata.Drives)); await Services.Export.ExportAsync(existingQuery.ChangeContext, new(outputFile, Human.Metadata.Drives));

  • [EXPORT] Added The.Composition.Options.ExportBatchSize to tune paging.

  • [LINQ] Added extension method IQueryable<T>.ChangeContext(). When used on queries that have a context (such as collections, GetAll() or .Query()) it will produce a copy of the query in the new context; otherwise, it's a noop.

v249.6.4

  • [WPF] Bugfix: SearchController would incorrectly verify the user's admin privileges when determining whether to create its subcontrollers in admin mode.

v249.6.2

  • [ORM] Bugfix: QueryTranslator would produce invalid IR if it needed to reproject a second time after performing a cardinality reducing reprojection.
  • [ORM] Bugfix: Recalculator was incorrectly comparing the createdOn date of entities to the local time rather than UTC time when deciding which entities to load for recalculation.

v249.6.1

  • [ORM] Cancelled entity store reads/writes are now considered "normal" for the purpose of logging, Info level rather than Error.
  • [WEB] Added an unconditional .ReadOnly() combinator to FieldSpec.
  • [WEB] Fields that didn't define an implementation of readonly-ness could fail to render when you tried to make them readonly; this is no longer possible.

v249.6.0

  • [MODEL] Fixed a bug saving model files unindented under .NET 6 (un-human-readable, bad for merge conflicts).
  • [MODEL] Added ModelFile.RequiresUpdate(), which will return true if the model will be upgraded when saved.
  • [MODEL] WPF editor integrations now detect that a file requires update even if the canonical event stream is unchanged, and make the editor saveable.
  • [MODEL] Addded a new version of the Audit feature, splitting audit logs into two tables - IAuditEntity and IAuditRelationship. The relationship audit table doesn't pack everything into JSON; it denormalises relationship inserts and deletes into columns which can be queried to (along with the EntityID column in the existing table) to build a history of an entity.
  • [MODEL] DataContractEntityStore supports the new IAuditRelationship.
  • [SQL] SQLEntityStore supports the new IAuditRelationship. When running a migration that turns on UseAuditV2, all triggers will be regenerated.
  • [WEB] Built-in pages like /Browse/{EntityName} now redirect to the home page if there's no such entity, instead of displaying an exception.
  • [WEB] IProgressHost implementations can now provide an IProgress<Status>. There are new WithProgress overloads to invoke operations which support progress.
  • [WEB] <CommandButtons> supplies a Progress<Status> to commands, and displays the output in a <ProgressBar>.

v249.5.0

  • [WEB] Commands can now use dependencies from M.E.DI, injected into their execution function whenever the command is activated (much like action methods on controllers). There are no breaking changes to commands themselves, just new overloads with generic parameters, but the constructors of DefaultCommandSpec and CommandContext have changed - subclasses now require EntityMetadataDictionary (available from DI as a singleton) and CommandContext no longer requires IServices (you can just inject it!).

    Old-style command: new Command("Do Thing", () => services.Navigation.Whatever()) // "services" closed over from some external source like CommandContext New-style: new Command<IServices>("Do Thing", services => services.Navigation.Whatever()) // no closure Or just: new Command<NavigationManager>("Do Thing", nav => nav.Whatever())

  • [WEB] Fixed a bug in BlobDocumentStore which prevented the creation of image thumbnails.

v249.4.0

  • [DOCUMENTS] Added nullability annotations for DocumentService, IDocumentStore and its implementations.

  • [DOCUMENTS] EntityDocumentStore now correctly produces DocumentNotFoundException instead of random LINQ exceptions.

  • [DOCUMENTS] DocumentService upload methods now have an optional IProgress<long> parameter which may report the number of bytes uploaded. So far, only BlobDocumentStore actually does so.

  • [WEB] The.Blazor now has a .NET 6 build with extra features.

  • [WEB] The.Blazor now depends on ImageSharp for image processing features. If it works okay, we'll move the dependency down to The.Core, so that we can provide the same API in web and desktop applications.

  • [WEB] Added components for dealing with documents. In The.Blazor.Controls:

    `<StreamImage>`, which displays an image based on a System.IO.Stream (buffering it on the client, but not the server).
    

    In The.Blazor.Entities: <RowDocument>, which presents a file or image (any IDocument implementation) for inspection and download. In The.Blazor.Cells: <FileCell> and <ImageCell>, for File and Image attribute types. In The.Blazor.Fields: <FileField> and <ImageField>, for File and Image attribute types. These components suffice to upload and download documents, but we will need to add more features over time - for example, nulling and progress reporting. The new cells and fields are enabled in DefaultListSpec and DefaultEditSpec. There aren't any document criteria yet - we don't have search functionality in the underlying document store. For now, it's best to turn off ShowInSearch for document attributes.

v249.3.0

  • [DOCUMENTS] FileDocument and ImageDocument now implement a common interface, IDocument.
  • [DOCUMENTS] Improved BlobDocumentStore performance by encoding thumbnail links as indexed tags.
  • [WEB] <ProgressBar> is now the same height as row elements like <RowButton> and <BoxChrome>.
  • [WEB] Added config options MaxUploadBytes, which will be used to cap the sizes of uploaded documents, and MaxImageBytes, which limits further images for the purpose of in-memory processing.
  • [WPF] CreateController now has overridable methods OnSavingAsync and OnSavedAsync that work the same way as the methods with the same name on DisplayController.

v249.2.3

  • [WEB] Fixed more combinator wrapping bugs in FieldSpec and CellSpec - not the same issue CriterionSpec had, but with the same symptom.
  • [WEB] Started some unit tests for spec combinators so this doesn't keep happening.

v249.2.2

  • [WEB] <DateBox> and <DateTimeBox> now bind more calmly to the <input> tags they ultimately represent, avoiding needless rerenders which lose focus state and make the control hard to use.

v249.2.0

  • Fixed The.Tool gen -h - binary hashing was broken for corefx (not that we use it anymore).
  • [ORM] Improved WebEndpoint TCP defaults on .NET Core.
  • [ORM] The Mutation thread-safety issue is now fixed... probably. The error detection code is still in place in case something goes wrong.
  • [WEB] <DateRange> has a new parameter, ShowExplainer; it's off by default, and unless you turn it on, the rather verbose explanation of the range's effect on the search will not be displayed.

v249.1.0

  • [WEB] Added support for IsReadOnly property to NullableDateField and DateBox widget

v249.0.2

  • [WPF] Bugfix: SidebarService.RegistrationChanged will now be called with the SidebarService instance as the event source rather than null.

v249.0.1

  • [ORM] Breaking: The consutructor for Mutation now requires an ILogger.

  • [ORM] Added debug level logging to relationship change notification & mutation broadcasts.

  • [ORM] Mitigated a thread-safety issue in Mutation. Previously, it was possible for relationship changes to not raise events because an earlier mutation on the same thread had not been correctly cleaned up - this was quite common in web applications.

    Although the cleanup can now happen post-hoc, there's still a race condition bug internally - the way this can manifest, in theory, is that if three threads simultaneously peform async operations, two of which are relationship mutations, then while all of them are awaiting the continuations can thread-hop such that one of the mutations crosses threads and the other crosses to a non-mutating thread, resulting, again, in a lack of raised events.

  • [WEB] Added debug level logging to entity change detection & command refresh.

v249.0.0

  • [WPF] Breaking: CreateModalController.Close is now async.
  • [WPF] CreateModalController has new virtual methods OnCreating and OnCreatingAsync which are called after a user clicks 'Create' and the modal is about to complete.
  • [WPF] DisplayModalController has new virtual methods OnCompleting and OnCompletingAsync which are called after a user clicks 'OK' and the modal is about to complete.

v248.1.0

  • [ORM] Fixed a thread-safety bug in The.Relationships.Mutation - this can be important when using Recalculator.
  • [WEB] Added error handling to criteria serialisation (previously, an unconvertible default could bring down <EntityCriteriaView>).
  • [WEB] Added the <DateRange> widget, which is now used by default for AttributeType.Date search criteria.

v248.0.0

  • [ORM] The ORM can now preload relationships in a new case: when you've loaded an object to which a reference refers, but the other side is non-navigable, any later lazy-loading attempt will discover the in-memory object before attempting a call to the datastore.
  • [WPF] Breaking: ScreenService.NotifyEntitySaved and EntitySavedEventHandler have a new boolean parameter 'deleted' to indicate that the entity being saved has been deleted.
  • [WPF] SidebarService has a new event handler RegistrationChanged which will be invoked when a sidebar registration changes or when a sidebar is reset.
  • [WPF] RecentItemsController will now remove a recent item if the user deletes it.
  • [WPF] Added a new Option for Grid screens: IsVirtualizable, defaulting to true. If disabled, there will be no UI virtualization, which improves scrolling performance at the cost of initial load performance. In future, we may change the default to false.
  • [WPF] Fixed ZomboBox bug when SelectedItem was changed externally.

v247.6.1

  • Improved test coverage for RPC when using obfuscated builds.
  • [ORM] Fixed an obfuscation bug in EntityDocumentStore which broke GetFileMetadata on .NET 6.
  • [WEB] Improved UpdateService to tolerate a missing wwwroot/ directory.

v247.6.0

  • [WEB] Added support for IsReadOnly property (used by the EditSpec classes) on various Field components including BooleanField, DateField, DateTimeField, DecimalField
  • [WPF] SearchController has a new method GetOrderedResultsAsync which will return its current results query in the same order as shown on screen.
  • [WPF] Bugfix: ZomboBox would display text out of sync with its selected item when displayed in a complex grid being scrolled.

v247.5.1

  • [WEB] Bugfix: The .Rename(), VisibleIf() and HiddenIf() combinators on CriterionSpec would have no effect if another combinator was used afterwards.
  • [WPF] Bugfix: Fixed exporting documents causing an error on .NET Core and later due to a breaking change in Process.Start between .NET Framework and .NET Core.
  • [WPF] Add AdminMode to SearchOptions and DisplayOptions. A SearchController in admin mode will create a ListController in admin mode which will open a DisplayController in admin mode which will display a ContentController in admin mode.

v247.5.0

  • [MODEL] Added a VS2022 version of the Instagile extension.
  • [ORM] DataContractEntityStore now has much better AuditLog support - the NewVersion/OldVersion json columns, while technically containing serialised operation content, were pretty useless. Now they're much more similar to the SQLEntityStore implementation.
  • [ORM] Fixed Guid2Json SQLEntityStore function, which was generating bare guids without quotes.
  • [WEB] Fixed a bug in <EditSection> which was not supplying an @key for its <EditField>s - this bug is not yet fully understood, but somehow when reusing field types but dynamically changing their position, on pages with a variable number of fields, their contents could get reused.
  • [WPF] Bugfix: Errors raised in EntitySelectorModel's SelectedItem setter escaped to the calling binding, which could not handle them gracefully.

v247.4.0

  • [EXTENSION] Instagile.vsix code generation now works when VS2022 or a .NET 6 SDK is installed. (The extension itself still only works in VS2019.)
  • [ORM] When registered in DI, composition roots now provide IDocumentStore and (if applicable) IDocumentStore as harvested dependencies.
  • [WEB] Added experimental <LookupCollectionField>, a single-row field which selects lookup entities via checkboxes in a virtualised scrolling list. This is proof-of-concept quality and is not yet enabled by default in DefaultEditSpec, but can be used by applications which require it for specific relationship properties.
  • [WEB] Added BlobDocumentStore, which uses Azure Storage as the backend.

v247.3.0

  • [WPF] EntityLink now has a context menu on its hyperlink which lets you copy the text of the entity.

v247.2.1

  • [SQL] Bugfix: DateTime constants emitted as strings had too much precision when compared against SQL datetime values. All DateTime constants are now emitted with three decimal places of precision.
  • [WPF] Bugfix: Fix approving a user registration request ignoring screen overrides when displaying the newly created user account.

v247.2.0

  • [WEB] Added ReadOnlyIf() method to FieldSpec
  • [WEB] Added support for readonly to StringField and TextField

v247.1.1

  • [SQL] Bugfix: Fix incorrect trigger migrations being generated when altering the IsAudited flag on an entity with existing relationships.

v247.1.0

  • [WEB] Added support for asyncronous CanExecute function in Commands

v247.0.0

  • [MODEL] There is a new UseAuditV2 model property, which must be set to True. Opening an existing .theModel file and saving it again will set the property. This event causes all audit triggers to be recreated.
  • [SEC] Bugfix: Removing password authentication claims from a user account would leave them orphaned without actually deleting them.
  • [SQL] Bugfix: DeleteEntity would audit the delete as having come from the user who last modified the entity, rather than the user who actually deleted it.
  • [SQL] Changes to relationships will now record an audit record if the audit model feature is enabled and the parent entity of at least one side of the relationship has the audit flag enabled.

v246.0.1

  • [WEB] Scroll Panel's ScrollContext property is now public

v246.0.0

  • [ORM] IDocumentStore methods now have an IPrincipal parameter. DocumentService and DocumentBase methods have a new optional IPrincipal parameter which will be passed through.
  • [WPF] Bugfix: ListController would open entities in the Creating state in a DisplayController. Now it will always use a DisplayModalController for such entities.
  • [WPF] TabController.AddAdvancedCriterion now returns a Task that will complete when the advanced criterion has been added.
  • [WPF] Breaking: AccountExtensions methods are now all async.
  • [WPF] Breaking: ClaimsAuthorisation.SetAdmin is now async.
  • [WPF] Breaking: PasswordAuthentication.Set/RemoveUsernameAndPassword are now async.

v245.4.2

  • [ORM] EntityDocumentStore now uses a trusted principal.

v245.4.1

  • [WPF] Fixed lazy load in ChangeNotification.AddDeepValueChangedHandler.
  • [WPF] Fixed lazy load in LookupInlineReferenceField constructor.
  • [WPF] Fixed lazy load in EntitySelectorModel constructor.

v245.4.0

  • [WEB] Bugfix: UpdateService.ListUpdates no longer attempts to use HttpContext, as this led to inconsistent output dependent on whether MVC or Blazor called it first. The output URLs no longer contain the application's base path; it's up to callers to add it if necessary.
  • [WEB] UpdateControllerBase now rewrites URLs returned from UpdateService.ListUpdates to the form expected by AutoUpdater.
  • [WPF] DisplayModalController's Entity and Editable fields are now accessible to subclasses.
  • [WPF] SearchOptions now includes CanOpen which if set to false will prevent the user from opening a SearchController's results.
  • [WPF] FrameworkApplication now sets UI culture in a way which works on .NET Core. If you need to use a custom culture in a The.WPF application, override CreateDefaultCulture() on your application subclass as well as setting Options.Culture when initialising The.Core. This change fixes the bug where many UI dates would display like "10/01/2000" instead of "10 Jan 2000" in a .NET 5 application.

v245.3.0

  • [IMPORT] ImportService has two new overloads for CopyData that allow for customisation of the import pipeline while also providing the model file via a Stream instead of a path.
  • [WPF] Bugfix: The 'Revoke Administrator Role' command button would sometimes be shown even when the user account being displayed was not an administrator.

v245.2.1

  • [SQL] Directly selecting an entity column now works for all attribute types and entity stores. For example:

    • .Select(some Currency) was broken in SQLite
    • .Select(some Instant) was broken in both SQLite and SQL Server
    • .Select(some BLOB) was broken in all entity stores!
  • [SQL] Query translation now supports instantiating POCO-like objects, using the same type mappings as for a single column, as long as there's exactly one constructor with the correct number of arguments.

  • [WEB] DisclosurePanel control now supports null Header.

v245.2.0

  • [MODEL] Generating code will now close the model editor first if it's open. This is to avoid a pitfall where the same EphemeralVersion is updated with different schemata.

v245.1.1

  • Added OnTrigger EventCallback to Tooltip control to enable loading of content dynamically when the tooltip is triggered.
  • [WEB] Bugfix: UpdateService now produces the correct path for non-incremental updates to WPF clients.

v245.1.0

  • [SEC] IAnonymousKeyProvider.CreateDefaultPublicKey has a new optional bool parameter "interactive" which, if true, allows the crypto subsystem to display UI while creating the public key. This is necessary for the Feitian driver to generate a key pair.
  • [SEC] PKIAuthentication has a new method CreateKeyPairInteractive, which will call IAnonymousKeyProvider.CreateDefaultPublicKey in interactive mode, which can allow a key pair to be generated.
  • [WEB] Bugfix: ClientLink now produces the correct URL when the application is not hosted at the server root.
  • [WPF] Bugfix: PKILoginHandler can now facilitate the initial generation of a key pair on a PKI token.

v245.0.2

  • Include bugfixes from v243 branch.

v245.0.1

  • [WEB] When using <EntityListView> to edit a selection, the Select All checkbox will now be unchecked if the list has 0 items.
  • [WEB] Bugfix: the Browse page didn't have a top level @key, which prevented rerenders when navigating between unparameterised search urls like /Browse/Foo and /Browse/Bar.

v245.0.0

  • [ORM] Added EntityReferenceProperty.ID, a Guid? which returns a referenced entity's ID regardless of whether the relationship is loaded (and without requiring a lazy load).
  • [SQL] Breaking: MigrationParameters has been replaced by a MEC-bindable POCO, MigrationOptions.
  • [SQL] Added IMigrationRunner interface. SQL-based entity stores now provide harvestable registrations for runner implementations. The batchTimeout parameter has been moved from runner construction to MigrationOptions.
  • [SQL] SQLEntityStore has a new option, useSqlAgent, which controls whether injected migration runners will set up an agent job to vacuum query tables. Note that the default is false, the opposite of the default when manually constructing an SQLMigrationRunner. Our use of SQL Agent is effectively deprecated, but being maintained for backwards compatibility.
  • [SQL] Migration is now cancellable, with the unit of granularity being a single migration and its attached datafixes.
  • [WEB] Breaking: MonitoredServiceBase is now StartupJobBase. Scheduled Jobs and Startup Jobs will probably a common interface eventually, allowing them to be described/monitored/initiated my admins.
  • [WEB] Mirrored some newer properties from The.Core.Composition.Options to The.Web.Composition.Options, where they can be set with Configure on the returned builder.
  • [WEB] Added MigrationJob, which updates a database to the latest version given some schema file (as specified in MigrationOptions).
  • [WEB] Added AddDataFix(), which registers a datafix in DI for automatic discovery by MigrationJob and UI. This is optional; DataFixes can be set in MigrationOptions instead.
  • [WEB] The Schedule class used in Job options is now MEC-bindable.
  • [WEB] New convenience overloads of AddTheEndpoint() which take a shared secret, using it to accept remote connections via SharedSecretAuthentication and falling back to WebAuthentication for local work.
  • [WEB] Mirrored some newer properties from The.Core.Composition.Options to The.Blazor.Composition.Options, where they can be set with Configure on the returned builder.
  • [WEB] <DataFixControlView> will now search for DataFixes in DI if the Include parameter is not set.
  • [WEB] Fixed <ProgressBar IsSmall> (it didn't do anything at all).
  • [WEB] <BarTable IsSmall> now applies small-row padding as well as just heights.
  • [WEB] Added optional StartupRequirements and <StartupView> which can be used to delay presentation until startup is complete. This is most useful in a blazor server app, but you can depend on a RemoteEntityStore backend by making PersistenceService.ConnectAsync() a requirement.
  • [WEB] Added Fragments.Empty.
  • [WEB] New convenience overloads of AddTheScopedFramework() which take a shared secret and an endpoint, using it to connect to a RemoteEntityStore without requiring credential push.
  • [WPF] Bugfix: LSCF would fail to display its Add button if its view was created while IsAdding was set to true, such as if it was being displayed in a modal which became hidden and was later recreated due to a deeper modal being displayed and then dismissed.

v244.1.1

  • [ORM] Bugfix: Endpoint would use a case-sensitive comparison when comparing usernames while using encrypted sessions.
  • [WEB] Adding ability to filter which rows in a selectable entity list view should have checkboxes.

v244.1.0

  • [WEB] Added ability to customize list header cells using the new HeaderSpec. CellSpecs have a Header property alongside their Label, which is now the fallback if no more-complex header is specified.
  • [WEB] Added SelectionContext, a new cascadable context which configures its child components to enable multiple selection of entity IDs. <CascadingSelectionContext> is a convenient way to cascade a SelectionContext and get events for selection updates.
  • [WEB] <EntityListView> supports selection using checkboxes and optionally a Select All header (defaults to not showing).
  • [WEB] Created nullable (tri-state) checkbox for indicating neither selected nor unselected.
  • [WEB] Added Fragments utility class with static methods to create common RenderFragments.
  • [WEB] <BarTable> now takes renderfragments instead of strings for its optional header cells; you can convert a sequence of strings to a sequence of fragments with .Select(Fragment.Text).
  • [WEB] <EntitySearchView> and <EntityCriteriaView> now have a small public api for external control (i.e. simulation of UI actions by pages embedding the views).
  • [WPF] UseIntegratedLogin no longer requires a The.Composition.Root - it uses the same one supplied to The.WPF.Composition.Builder.
  • [WPF] Minishell now supports a basic version of shell-integrated autoupdate. Supply an HttpClient to Minishell.Create() and it will perform an update check before proceeding to the main controller.

v244.0.0

  • The.Core now has a net5.0 build. A netstandard2.0 build is still provided for applications that have a .NET Standard model project shared between .NET Framework and .NET apps; it will probably go away when .NET Framework support does.
  • [WEB] Added <DataFixControlView>, an alternative way to run custom migrations (DataFix objects from The.SQL.Schema).

v243.3.4

  • [MODEL] Breaking: The UserRegistration model feature has been updated to support other kinds of authentication. Existing user registration requests will be invalid after the feature upgrade.
  • [MODEL] Bugfix: the extension method IReadOnlyDictionary.GetOrDefault() incorrectly expected an IReadOnlyDictionary<TKey, TValue?> as receiver instead of IReadOnlyDictionary<TKey, TValue>.
  • [ORM] Breaking: UserRegistration.Request has been broken up into several methods to allow for clients to request registration for multiple kinds of authentication.
  • [ORM] Some of the types in The.Core now have nullability annotations. This is a source-breaking change (adds warnings only) for applications using <Nullable>enable</Nullable>. Most of the code isn't annotated yet, but we have coverage for a few namespaces and some of the key abstractions.
  • [WEB] Bugfix: Scheduling a task for Sunday, on Saturday, would skip an extra week to run next Sunday instead.
  • [WEB] Added MonitoredServiceBase, an IHostedService implementation which logs execution attempts and reports completion via a Task. This can be a useful base for hosted services with dependencies which should execute in a predictable order - for example, migrations run on startup.
  • [WEB] Added new constructor parameter automaticallySetAdminFlag for UserRegistrationControllerBase which will add an admin claim to user accounts that it creates automatically.
  • [WPF] Added PasswordOnlyLoginHandler, an ILoginHandler implementation for PasswordAuthentication when using the UsernameProvider property which only allows password input. This can be used when the client's username can be derived from the environment, e.g. the current windows identity.
  • [WPF] Added IntegratedLoginOptions.UserRegistrationController, which if set allows ILoginHandlers to orchestrate user registration from the login screen. Currently only supported by PasswordOnlyLoginHandler.

v243.3.3

  • [MODEL] Bugfix: The model editor would show the generated display label if a label override had been specified, and would show no label at all if no override had been specified.

v243.3.2

  • [WEB] Optimisation: ScheduledJobBase.Reschedule() won't do anything if the schedule hasn't changed.

v234.3.0

  • [ORM] The serialisation system used persistence operations now supports double values. We don't have any attribute types that correspond to double, but you might want one for maths internal to a query.
  • [SQL] Added a useSQLAgent flag to SQLMigrationRunner which can be disabled to prevent the use of SQL Agent for nightly cleanups even if the server supports it.
  • [SQL] SQLEntityStore and SQLiteEntityStore now provide an IDMLDialect registration in HarvestDependencies(), allowing some degree of db-agnostic query authoring.
  • [SQL] QIR DeleteStatement now supports an optional limit/take-count.
  • [SQL] Query translation now supports DateTime.AddDays(), as long as the argument can be evaluated at translation time.
  • [WEB] New feature: hosted services that represent regular scheduled maintenance tasks. The.Web.Jobs namespace now contains a Schedule class and ScheduledJobBase, along with some commonly useful services - RecalculationJob to regularly recalculate properties, VacuumJob to replace the cleanup process that SQL Agent usually does in-app.

v243.2.0

  • [ORM] Batch property recalculation now supports [CalculationDependency] on collections. This is only appropriate for small collections - but if the calculation itself depends on the whole collection, that's only appropriate for small collections too.

v243.1.3

  • [WEB] Fixed <BoundStatus> bug causing it to reset to the initial status on every update.

v243.1.2

  • [WEB] Part of the IEditSpec override API was SectionSpec, a custom IGrouping of binding/field pairs. These pairs were exposed as valuetuples, but this triggers https://github.com/dotnet/roslyn/issues/21727 or some similar issue. The spec now uses a concrete inner type, SectionSpec.Row.

v243.1.1

  • [SEC] Added some convenience contructors to SharedSecretAuthentication.
  • [TEST] SkipTestException (used with [SkippableFact]/[SkippableTheory] from The.Xunit) is now public.
  • [WEB] <InclusiveChoice> had an incorrect implementation of INullableWidget; although the IsNull checkbox worked, the choice, as a whole, could not be null. This meant that a criterion using this widget was always-on, contributing useless SQL.
  • [WEB] Replaced the hierarchy of CriterionSpec subclass constructors with factory methods (overloads of CriterionSpec.Create). This simplifies custom criteria and improves interaction with nullability. Predicate functions are now guaranteed to receive non-null inputs at the type level (previously guaranteed at runtime) and don't need to include or elide useless null checks. Overloads which use search specification objects no longer need to (but may) explicitly set the traits phantom type.

v243.1.0

  • The.Model now has nullable reference type annotations.
  • The.Model.WebEditor now requires .NET 5 (up from .NET Core 3.1).
  • [MODEL] Models now have a default namespace, meaning CreateModel events are no longer strictly necessary. Eventually they will be removed, as ChangeModel has all the same features.
  • [MODEL] Added utility extension method .WhereNotNull(), which filters sequences and narrows the type.
  • [SEC] WebEndpoint will now translate certain HTTP status codes (401, 403, 407) to SecurityError instead of throwing an exception (which becomes a TransportError). This allows us to include a fairly specific AuthenticationFailure code and display specialised error messages.
  • [WEB] RecalculationService now supports calculating only specified entity types. <CalculationControlView> exposes this feature as optional Include and Exclude properties; a <CalculationControlView Include="{Foo.Metadata}" /> will recalculate only properties of entity Foo.

v243.0.0

  • [SEC] Added AuthenticationProtocol.MatchingAmbientIdentities, which indicates that a lower layer (e.g. HttpClient or IIS) will provide authentication. Instagile will not itself provide message security in this mode but will verify that the user's claimed identity matches the ambient identity on the server.
  • [SEC] Breaking: IRemoteAuthentication has been removed and merged into IAuthentication.
  • [SEC] VerifyIdentity now verifies that the provided subject matches the current identity.
  • [SEC] PKIAuthentication no longer supports VerifyIdentity.
  • [SEC] PasswordAuthentication no longer supports pull mode.
  • [WEB] Removed unused interface ISelectionWidget<T>.
  • [WEB] Fixed bug in <ComboBox> - if OptionsQuery or OptionsQueryFactory were supplied instead of Options, the control would fail to render. This also affected users of <ComboReferenceField>.
  • [WEB] Fixed nullability of FieldSpec.Rename() - some parameters were incorrectly typed as string instead of string?; you need to be able to supply null to remove the label entirely.
  • [WEB] The various framework composition functions will now register a singleton IAuthentication.
  • [WEB] Added a new variant of AddTheEndpoint/AddTheLegacyEndpoint which does not require an IAuthentication to be specified.

v242.0.0

  • [WEB] The.Blazor now has nullable reference type annotations. Applications using the package can opt in to the use of NRTs by adding <Nullable>enable</Nullable> to a project file or #nullable enable in a single source file. Unfortunately, NRTs are of limited use in .razor files for now; they work in C# @-locks, but component parameters aren't checked.
  • [WEB] Fixed numerous internal null-safety bugs and logical errors.
  • [WEB] Create page now has an optional EntityFactory parameter which will be used to construct the new entity if supplied.
  • [WEB] The.Web now has nullable reference type annotations. Applications using the package can opt in to the use of NRTs by adding <Nullable>enable</Nullable> to a project file or #nullable enable in a single source file.
  • [WEB] The.Web now requires .NET 5, increased from .NET Core 3.1. This prevents clashes between optional shims included in netstandard2.0 builds of libraries.
  • [WEB] Creating an account using UserManager from ASP.NET Identity no longer automatically enrols it for PasswordAuthentication. UserManager.AddPassword does, however! In sum, it's now up to an application whether it's using passwords or some other login mechanism.
  • [WPF] Bugfix: User preferences could specify that a list or grid column be so small as to not be displayed at all. The minimum width of a column set from user preferences is now 50 pixels.
  • [WPF] Modal screens will now use the name of the type of their screen model instead of their screen title as part of the preference key for modal width and height.

v241.3.2

  • Enabled XML documentation file generation. Some of the public types and members in the framework have doc comments, which will now be visible in intellisense when using NuGet packages. We'll increase documentation coverage over time.
  • [WPF] Bugfix: DisplayController would load the entire table of every lookup relationship of the current entity type into the same context.

v241.3.1

  • [WEB] Fixed CellSpec constructor bug - only the (PropertyInfo) constructor worked, and combinators were also broken so you couldn't work around it.

v241.3.0

  • [WPF] New SystemConverters members DoubleToRadiusConverter and DoubleToThicknessConverter (which use the double as a uniform thickness).
  • [WPF] New control HelpMarker, a themeable visual indicator that some form of help is available. The default visual appearance is a circled question mark.
  • [WPF] IField has a new property, string? HelpText. If non-null, the help text will be displayed as the tooltip on a HelpMarker beside its label. (By default, fields without labels won't get a marker or tooltip). HelpText can also be set at the view level using a property of the same name on FieldControl.
  • [WPF] Added an IField combinator .Tooltipped(), which sets HelpText using the usual wrapping mechanism.

v241.2.0

  • [ORM] Added EntityCollectionProperty.EagerLoad(), which will cause an unloaded collection to become loaded with the given entities as its contents.
  • [ORM] GetByID[Async] will now eager-load many-to-many collections specified in includeRelationships. (It already loaded one-to-one references and one-to-many collections).
  • [ORM] The generated Foo.GetByID[Async] static methods now have additional overloads with the extra options added to the GetByID family in 237.0.
  • [SEC] IRemoteAuthentication.PushCredentials now uses the AuthenticationFailure error reporting system.
  • [SEC] The IPrincipal supplied to ILoginHandler.OnLoginFailed is guaranteed to be unauthenticated, so the only useful part of it is the error code. The interface has been changed to just accept an error code. This also applies to the delegate parameter to UseIntegratedLogin().
  • [WPF] Added an explicit Attach property to PasswordBoxHelper so that it isn't subject to the vagaries of binding timing.

v241.1.1

  • [WPF] Bugfix: Adding advanced criteria was broken on .NET Core.

v241.1.0

  • [WPF] Added GridModalController: a modal containing a GridController.

v241.0.0

  • [SEC] Breaking: Authentication errors have been refactored. IPrincipal now provides (if unauthenticated) a structured ErrorCode instead of a string ErrorDescription. This has a number of small API-breaking changes in various places; for example, CreateUntrustedPrincipal() no longer requires a "reason" argument and IAuthentication must now return an AuthenticationFailure enum rather than throwing exceptions.

  • [SEC] PKIAuthentication now supports push mode; its credentials are a string key password.

  • [SEC] IAnonymousKeyProvider now has separate methods to return each of its public and private keys. This is to avoid requiring the private key password or triggering a password prompt for uses that only require the public key.

  • [WEB] Breaking: Swapped the names of CellSpec and ColumnSpec. These were simply backwards and it's better to rip off the bandaid now.

  • [WEB] EntityListView's initial column is now controlled by a ColumnSpec like the other columns. IListSpec just returns it as the first element from the existing method DefineColumns(), but the convenience base class DefaultListSpec gives you a specific method to override if you want to replace it.

  • [WPF] Bugfix: ImageControl and FileControl weren't responding to clicks on their preview image.

  • [WPF] Breaking: AutoUpdater behaviour settings are now constructor parameters instead of method parameters.

  • [WPF] Breaking: Instead of an optional HttpClient for autoupdating, LoginScreen constructor takes an optional AutoUpdater, letting you configure update options like controllerPath and ensureExit. UseIntegratedLogin() supports the same options via IntegratedLoginOptions and its configure() delegate.

  • [WPF] Added PKILoginHandler for use with LoginScreen.

  • [WPF] Added UseIntegratedLogin() parameter onLoginFailed, which lets you customise the error message displayed and potentially do other app-specific work.

  • [WPF] If the framework defaulted to using ClaimsAuthorisation, UseIntegratedLogin() will also do so (meaning that you'll get role-management commands on account screens).

  • [WPF] Added PasswordBoxHelper, a utility class with an attached property which allows you to bind to PasswordBox.Password.

  • [WPF] ILoginHandler now provides a Model instead of a View, using data templating to pick a control. This allows applications to customise their login UI, using a template override like this example:

      <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
      				xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
      					xmlns:login="clr-namespace:The.WPF.Shell.Login;assembly=The.WPF">
      	<DataTemplate DataType="{x:Type login:PasswordLoginModel}">
      		<Border BorderBrush="Red" BorderThickness="2">
      			<login:PasswordLoginView />
      		</Border>
      	</DataTemplate>
      </ResourceDictionary>
    

v240.4.1

  • [EXTENSION] The.Web should no longer block code-generation in .NET Core applications. It had the same problem as The.WPF - ref assemblies in a shared framework being loaded instead of the underlying runtime assemblies - but the problem was less obvious as The.Web has no templates of its own.

v240.4.0

  • [EXTENSION] Added an optional extra toolbar with commands for debugging code generation. Specifically, you can do a "dry run" of codegen which will assemble all the info for the generator and give you the path to its input directory instead of actually running it.
  • [EXTENSION] Added a new generator command which runs on a dumped directory of assemblies like the ones the extension can now produce.
  • [EXTENSION] The code generator executable can now be run standalone, taking a command as an argument instead of on stdin, for debugging.
  • [EXTENSION] The model editor now supports undo/redo of tag edits.
  • [EXTENSION] Fixed NRE in the model editor's tree-search feature (click in the list and type).
  • [EXTENSION] Fixed NRE in solution parsing (to discover codegen references).
  • [WPF] Added IServices.ReloadSurface(). This function is similar to DestroySurface() - a nonobservable, potentially asynchronous ui operation which acts as if the user had clicked the refresh button (and will therefore show 'discard changes?' dialogs).

v240.3.1

  • [EXTENSION] The.WPF templates should fairly reliably load for code-generation in .NET Core applications. Previously, whether this worked was based on the the first letter of your application's name.

v240.3.0

  • [WPF] Codesigning can now be extended to sign extra dlls by adding SignedAssembly items to the project. You can also prevent the main output from being signed using <SignedAssembly Remove="$(OutputPath)$(TargetFileName)" /> (but if you just want to turn off codesigning entirely, use property <SignatureEnabled>False</SignatureEnabled>).
  • [WPF] When building .NET Core applications that produce a .dll and a wrapper .exe, both will now be <SignedAssembly>s by default.

v240.2.1

  • [EXTENSION] Fixed codgen dll lookup for assemblies with stubs in Microsoft.NET.Sdk but implementation in Microsoft.WindowsDesktop.Sdk - WindowsBase.dll, for example.
  • [WPF] LoginScreen performs update checking on the threadpool so that it doesn't block the main thread while installing updates (http requests are async, but unzipping the stream as we read it is not).
  • [WPF] AutoUpdater public methods accept an optional IProgress for reporting the state of the update process.

v240.2.0

  • [EXTENSION] Instagile.vsix uses the analyzers and primitives from https://github.com/Microsoft/vs-threading/ to improve thread-safety.
  • [EXTENSION] The 'Generate Code' command has been split into two separate commands: one runs code-generation for older .NET Framework apps, one for newer .NET Core apps. Previously, codegen always ran in .NET Framework, which was flaky if a solution contained both types of project and completely nonfunctional if it contained only .NET Core code. .NET Standard template libraries (like The.Core) will work in both modes.
  • [MODEL] Improved heuristics for loading assembly dependencies during code generation, particularly on .NET Core. Note that you need updated nupkgs rather than an updated extension for this to work - assembly loading is done by the copy of The.Model referenced in your solution!

v240.1.6

  • [WPF] Removed pre-UseWpf support for SDK projects. Once upon a time, it wasn't officially possible to build .NET Framework WPF projects using SDK-style projects, but you could achieve it with enough MSBuild hacks, which we supplied. Newer versions of the .NET SDK (3+) support this configuration via <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop"> and <UseWPF>True</UseWPF>. Our hack wasn't getting in the way of this, but it also needlessly applied to .NET Core WPF projects, causing build warnings in net5.0-windows projects. Those warnings are now gone.

v240.1.5

  • [WPF] AutoUpdater is now compatible with CLR stubs, PublishSingleFile and other techniques that wrap the entry assembly in some kind of launcher.

v240.1.4

  • [WEB] Robustness fixes (logging, error handling, etc) for autoupdate incremental update.
  • [WEB] Updates can now be over 30MB in size on Azure.

v240.1.0

  • [ORM] Bugfix: DataContactEntityStore was failing to capture the identity/timestamp of version conflicts because it didn't understand that modifiedOn is now an Instant.
  • [SEC] ClaimsAuthorisation (formerly ProfileAuthorisation) is now used by default if user accounts are enabled in the model and no other IAuthorisation is registered.
  • [SEC] Automatic migration from the IUserProfile "realm claim" model to IUserAccount's "username" model is now more robust. Accounts that don't yet have usernames won't wipe the locally-determined username, and the backwards compatibility mechanism will trigger earlier, in time for the authorisation cache to load.
  • [SEC] LoginWindow handlers can specify custom handler-specific commands.

v240.0.0

  • [WEB] Added incremental update support to UpdateService and UpdateControllerBase. A new endpoint /update/partial serves a small archive containing only client-specified files.
  • [WPF] Breaking: DeferredMenuBuilder.Init now requires an IPrincipal.
  • [WPF] AutoUpdater will now perform incremental updates if the server supports it. Existing files which match given hashes will be kept and the remainder downloaded.
  • [WPF] Bugfix: A race condition could occur after logging in where the menu builder could be given a null or unauthenticated principal.

v239.2.5

  • [WEB] <BoundFunction> and <BoundTask>, if re-rendered with an unchanged binding, will not re-execute it.

v239.2.3

  • [WEB] <ComboReferenceField> now applies modelled entity sorting.

v239.2.2

  • [WEB] Added ExceptionContext and <CascadingExceptionContext>, used to customise <ExceptionView> display and handle their errors at a higher level. This will likely be combined with other 'context' features at some point, or refactored when .NET 6 introduces error boundaries.

v239.2.1

  • [WEB] Thanks to a godawful hack, unlabelled fields in a <FieldGrid> can now display across the whole width of the grid. This can be done with a <FieldRow Label="@null"> or using a FieldSpec with label=null.

v239.2.0

  • [WEB] <EntityBox>, which is used in reference criteria, now respects default entity ordering.

v239.1.0

  • [WEB] ValueCellBase and ValueFieldBase now support updates to the bound property from non-dispatcher threads.
  • [WEB] Added CellSpec<T> where T:IEntity as a convenience for supplying typed PropertyBindings.

v239.0.4

  • [WEB] Bugfix: Fixed rendering error in <CalculationControlView>.

v239.0.3

  • [ORM] Bugfix: TypeBox would incorrectly identify any public type as an anonymous type.

v239.0.2

  • [MODEL] Bugfix: The directionality of the UserAccount to UserProfile relationship has changed to make it consistent with the feature upgrade events.
  • [MODEL] Application models that added the User Accounts feature since v237 but prior to this version will require manual editing.
  • [WPF] EntityDocumentStore will no longer download the entire document when downloading document metadata.

v239.0.1

  • [WEB] <BoundStatus> now begins at to 0/1 (determinate 0%) instead of indeterminate state. A new InitialStatus parameter can be used to override this behaviour.

v239.0.1

  • [MODEL] Bugfix: The IUserAccount<->IUserProfile mapping of entities to interfaces was backwards.

v239.0.0

  • [ORM] Breaking: IDocumentStore's methods now take an instance of IServices rather than an IEntityContext.

  • [ORM] Breaking: OpGenerator AsEnumerable, First, FirstOrDefault, Single and SingleOrDefault now return a ReadOperation rather than a QueryEntities so as to support selecting values.

  • [SQL] SQLiteEntityStore now supports selecting Nullable<T> columns.

  • [SQL] Added query translation for anonymous types as a final selection. We now support queries like this:

    from t in ComplexThing.Query(ctx)
    select new { t.MyString, t.MyDate, t.MyInteger }
    

    Or like this: ComplexThing.Query(ctx).Select(t => new { I = t.MyInteger + 1, S = (t.MyString + "X").Substring(1) })

  • [SQL] Bugfix: string concatenation with + produced incorrect SQL. "x" + "y" would generate 'x' + 'x' instead of 'x' + 'y'.

  • [WEB] <BoundProgress> has been rewritten with an API based on a single function binding instead of Subscribe and Unsubscribe callbacks. A new component, <BoundStatus>, can perform the previous implementation's function of transforming The.Utility.Status-based updates into a renderable current state.

  • [WEB] <ProgressBar> now has a consistent cross-browser theme.

  • [WPF] Bugfix: Approving a user enrolment request would display an error when attempting to display the newly created user account.

  • [WPF] Bugfix: Value collection fields would not reliably cause updates to their underlying relationship's changedness.

  • [WPF] Breaking: SectionedCollectionFieldBase and its implementations no longer have a SubscreenFactory property and constructor parameter, and the type of the parameter for CreateSubscreen has changed.

  • [WPF] Bugfix: DisplayController would not warn about changes when clicking its Refresh command button. This behaviour is implemented in a new overridable method ConfirmRefreshAsync.

  • [WPF] Breaking: DisplayModel.RefreshCommand is now different from the refresh command in its Commands list.

  • [WPF] Bugfix: DisplayControllers created through ScreenService would rarely ever be freed.

v238.1.2

  • [MODEL] Bugfix: Account model feature upgrade would not create new user account entities before removing the old relationship between user profiles and claims.

v238.1.1

  • [WPF] Bugfix: Fix NRE when invalidating a principal with authoritative authentication.

v238.1.0

  • [MODEL] Bugfix: Account model feature upgrade would generate a relationship with incorrect multiplicity between UserAccount and UserProfile.
  • [ORM] Bugfix: Removed a synchronous read in EntityDocumentStore.GetImageMetadata that could lead to a deadlock when run on the WPF dispatcher while using RemoteEntityStore with sessions.
  • [WEB] Bugfix: Fix NRE in EntityEditView if its CommandContext is null.
  • [WPF] FileControl and ImageControl can now act as the drag source for drag and drop.
  • [WPF] FileField and ImageField can now act as the drop target for drag and drop.

v238.0.0

  • [WEB] Added IWidget.IsInvalid. Like HasChanges, this is just an appearance change - the meaning of 'validity' is determined by the widget's consuming component.
  • [WEB] <NumberBox>, which presents data as text using The.Values conversions, now detects conversion failures and preserves user input, displaying an error state until conversion succeeds.
  • [WEB] ValueFieldBase (and its subclasses, which include all built-in attribute fields) now preserve user input, refraining from reformatting it if the Value binding does not roundtrip. This applies, for example, when attributes have a 'canonical' form like Date attributes lacking a time or String attributes trimming text.
  • [WEB] Changed default text on bool criteria (which give you three radio buttons) from True/False/Unknown to True/False/Any.
  • [WPF] Breaking: SessionService.Logout is now LogoutAsync.
  • [WPF] SessionService.LogoutAsync and LoginAsync will now wait for a previous login or logout operation to complete before proceeding.
  • [WPF] SessionService.LogoutAsync will now invalidate the current principal.

v237.0.0

  • [MODEL] Equals() and Diff() methods on some element snapshots now support comparison flags for ignoring some kinds of differences.

  • [MODEL] User accounts feature updated to v3. IUserProfile has been split into two entities, IUserAccount and IUserProfile. The former has a canonical username and the relationship to IUserClaim; the latter is user-writable, containing optional data like preferences and displayname.

  • [ORM] Breaking: The GetByID family of methods on PersistenceService have new signatures and features. They now accept two extra arrays of IEntityInfo metadata, used to specify types to cache as Get/AddAll sets. Types specified in includeCounts[] will be frozen by count (as GetAll usually does); types specified in includeEntireTables[] will be fully preloaded, which may sometimes be appropriate for reference data.

  • [ORM] Breaking: Removed IEntityContext.Remove() and IEntityContext.RemoveAll(). These APIs are not useful, as the "removed" entity still has Kernel.Context, which is immutable.

  • [ORM] Breaking: Added new metadatum SectionInfo. This works similarly to other infos - IEntityInfo has a Sections property, the typed generated metadatas have FooSection, etc. EntityInfo.Sections and SectionInfo.Properties are sorted in modelled display order. Sections do not have a runtime representation, so there's no corresponding collection in the EntityKernel. Some properties have been rearranged, notably replacing string DisplaySection on PropertyInfo with SectionInfo Section.

  • [ORM] Bugfix: When attempting to connect to a legacy-mode IEntityStore, connection failures were mis-diagnosed as a legacyness mismatch.

  • [SEC] The interaction between Identity objects and the optional Accounts feature has been refactored. An Identity is no longer specific to a Realm; instead, it has Claims provided by zero or more realm authenticators. Its Name has been renamed to Username, because the semantics are slightly different: usernames may come directly from an authenticator, but when using Accounts they may also be canonicalised in the account entity itself.

    Under this new scheme, it's now possible for a single IUserAccount to have multiple login methods - claims from multiple authenticators can be stored in the account's IUserClaims. For backwards compatibility, there is a new setting Options.RealmClaimsMigration, on by default. When this flag is enabled, the old-style "realm claims" will be migrated to account usernames on-demand.

  • [SEC] For transitional purposes, PasswordAuthentication now has two modes: push and pull, determined by which constructor overload is used. If a getLocalCredentials delegate is supplied provided then the PasswordAuthentication is in the old 'pull' mode; otherwise, 'push' mode is used. The new PushCredentials method is available only in push mode.

  • [SEC] PasswordAuthentication and NTLMAuthentication have some new properties for configuring login UI and authentication policies.

  • [SEC] When authentication fails due to encryption (using AuthenticationProtocol.EncryptedSession) the cause of failure is now logged. Failure causes for AuthenticationProtocol.VerifiedOperations were already being logged; this was just an accidental omission.

  • [SEC] The various Profile______ involved in ASP.NET Core Identity integration are now named Account______.

  • [SEC] We've been using the term 'claim' in both the domain of authentication (referring to a fact about an identity) and in the domain of authorisation (referring to an asserted ability to access a resource). The.Security.Claim, the one used in authorisation, has been renamed to Permission in order to disambiguate. Note that we already had PermissionSet and PermissionSerialiser to operate on a collection of (formerly) claims!

  • [SEC] ProfileAuthorisation is now named ClaimsAuthorisation, which would previously have been even more confusing.

  • [SEC] Brought forward a partial version of planned future IAuthorisation changes: the interface's on-demand, synchronous CheckAccess method has been replaced with a batched, asynchronous LoadPermissionsAsync(). Expect the "PermissionSet" returned by this call to change further in future releases!

  • [SEC] The Check/Assert methods on IPrincipal no longer require data access and therefore are no longer dependent on lazy loading. Principals are created with their authorisation permissions baked in; this is cached in entitycontexts, but not in endpoints (meaning that backend servers will re-check authorisation without need for cache invaldiation).

  • [WEB] <Bound____> components which can fail now use <ExceptionView> if no ErrorContent is set. ExceptionView has been improved with some display options and a copy-to-clipboard action.

  • [WEB] Added <CascadingUserAccount>. Like the built-in <CascadingAuthenticationState>, this component cascades a task to its children, which will either

    • resolve to an IUserAccount subclass
    • resolve to null (if not logged in, or if logged in as an identity with no account)
    • throw an exception (for various reasons like being unable to connect to the database) This component allows applications to load an account centrally and once per-circuit, while keeping rendering decisions about fallbacks and error display local. It also serves the same purpose that IShell.InitSecurity does in The.WPF, auto-creating accounts from bare identities.
  • [WEB] Fixed WebAssembly startup attempting to read a license file (which are not available, and not needed - we license the server instead).

  • [WEB] Breaking: The menu builder delegate now accepts an IPrincipal as a parameter and is now called BuildMenu.

  • [WPF] Breaking: UseIntegratedPasswordLogin is replaced with UseIntegratedLogin, which inspects SecurityServiceCore.Authentication and provides an appropriate login UI using LoginScreen. Many of UseIntegratedPasswordLogin's parameters are now properties on PasswordAuthentication or the new IntegratedLoginOptions.

  • [WPF] Breaking: LoginScreen now requires an ILoginHandler rather than PasswordAuthentication-specific parameters. PasswordLoginHandler and WindowsLoginHandler have been provided.

  • [WPF] Breaking: MemoryCredentials is gone; PasswordAuthentication now serves this purpose when in push mode.

  • [WPF] Bugfix: Definitions.ApplyStringContainsWords would unnecessarily check for empty strings if the user entered consecutive spaces.

v236.4.0

  • [WEB] Default____Spec<T> classes (the generic variants) now have a virtual Match() method so that you can create default defaults - for example, replacing all Time fields in an application.

  • [WEB] DefaultEditSpec<T>.DefineBinding() now returns a PropertyBinding<T>, which allows you to specify typed lambdas like so:

    protected override `PropertyBinding<Human>` DefineBinding(PropertyInfo metadata) `=>` metadata.Name switch
    {
        nameof(Human.Nickname) `=>` h `=>` h.props.Nickname,
        nameof(Human.Age) `=>` h `=>` h.props.Age,
        _ `=>` base.DefineBinding(metadata)
    };
    

v236.3.0

  • [WEB] Added IProgressHost, a sort of moral equivalent of The.WPF's ProgressController.
  • [WEB] CommandContext now has a ProgressHost property, which can be used by commands to display some progress UI while they're busy. Commands presented in a <CommandButtons> will use a progress bar for this UI, displayed after waiting for Options.ProgressDelay.
  • [WEB] The default entity save commands now use ProgressHost.

v236.2.0

  • [SQL] Query translation now supports some value type conversions - anything.ToString(), int.Parse(), long.Parse().

v236.1.0

  • [ORM] Added overloads of ExportService.ExportAsync which can write to a stream instead of a file.
  • [WEB] List commands, which operate on an IFrozenQueryable<T>, will now be regenerated when the ListView query is updated - for example, when you perform a search on a Browse screen.

v236.0.0

  • [WPF] Breaking: ShellCommand no longer has asynchronous constructor overloads. Please use AsyncShellCommand instead.
  • [WPF] Breaking: ValueSectionedReferenceField.Delete has been renamed to DeleteAsync.
  • [WPF] ShellCommands and SynchronousScreenCommands will now prevent reentrant invocation of their commands.

v235.5.0

  • [WEB] IEditSpec can now be used to define a custom load function for the use of Edit pages (or for anyone who calls ScaffoldService.LoadEntity).

v235.4.0

  • [WEB] Combinators can now control more things when applied to specs with enough generic parameters - .Component<T>() can be used to change the UI associated with a column/criterion/field and .Default() can change a criterion's starting value (including setting the value based on runtime data).
  • [WEB] <NumberTraitsBox> now supports Traits.Multiline.

v235.3.2

  • [WEB] If all of the fields in an EditSection are hidden, the section will be hidden as well.

v235.3.1

  • [ORM] Added a new remote authenticator SharedSecretAuthentication. This wraps a non-remote authenticator (for example, NTLM or HTTP) and supports ticket-signing (VerifiedOperations protocol) using a secret key. It will probably evolve a bit as we reconcile distant parts of the overall security framework.
  • [WEB] New features for supporting imports and raw data access for RemoteEntityStore - AddTheLegacyFramework() and AddTheLegacyEndpoint(). The latter depends on the former. If a legacy endpoint has been provided, ProxyControllerBase will provide extra apis at subpath "legacy/" (so instead of connecting to http://foo/proxy/, you'd connect to http://foo/proxy/legacy/).
  • [WEB] <EntityEditView> now has fully dynamic rendering - if any change is made to the entity, its component tree will update. In practice, we don't want to re-render most fields. ValueFieldBase and the new similar CollectionFieldBase will not render unless their property has been swapped or its value/collection has changed. You can override this with the standard component lifecycle method ShouldRender().
  • [WEB] Edit, List and Criterion overrides are now consistently schematised. In all cases, the I___Spec is asked to create immutable, cacheable definitions, which are then reified as a ___Model at runtime by supplying a ___Context which is also available to customised UI. The specs have 'combinator' methods which modify the runtime model creation based on live data - Rename(), VisibleIf(), HiddenIf(), etc.

v235.2.1

  • The.Xunit no longer supports netstandard2.0 - it has builds for net5.0, net5.0-windows and the legacy net472.
  • All tests which run on a .NET Core version now use .NET 5 (instead of a mishmash of 2.1, 3.1 and 5). The only package which doesn't support at least net5.0-windows is The.Extension.
  • release.bat has been rehabilitated, and manual releases are possible once again.
  • [WEB] Fixed display error when stacking <ComboBox>es on top of each other - the clear button of lower boxes would display over the dropdown portion of an open higher box.

v235.2.0

  • [ORM] Updated DataContractPersistence template to support properties with the same name as an entity in more circumstances.
  • [WEB] <RowButton> now has an ExtraClasses parameter like other tag-wrappers.
  • [WEB] Added <BarTable>, a control which provides the styling of <EntityListView> (boxy headers, padded text, etc) without its special data features. A BarTable has Headers set as a list of strings, and should contain <tr> elements as direct content to provide the table body. It will use full-size or small-size rows depending on the IsSmall parameter.

v235.1.0

  • [WEB] Each I___Spec override interface has been acquiring some kind of context parameter - CommandContext, FieldContext, etc. ICriteriaSpec now receives a CriterionContext, which is also available to criterion components as a CascadingParameter.

v235.0.0

  • [MODEL] Added a sanity check in SnapshotBuilder to prevent Attribute.IsTransient from being reset by combined change events - this would lead to incorrect DDL generation.

  • [WEB] Browser differences require us to supply different styles in some cases. In order to support this, some of the core layout mechanisms have been refactored to be more robust:

    • <SectionPanel> now allows arbitrary direct content, rather than specifically expecting a sequence of <PanelRow> components.
    • <RowsPanel> is now <FieldGrid>, a non-Panel component which displays labelled, variable-height pieces of content. <PanelRow> is now <FieldRow> and can only be used in a grid (this will be enforced in .NET 6 once https://github.com/dotnet/aspnetcore/pull/29767 is merged).
    • Unlike its predecessors, <FieldGrid> can be used inside a <ColumnsPanel>, in which case the columns will be correctly balanced row-by-row.
  • [WEB] FieldSpecs now have a nullable string Label, rather than a boolean HasLabel which uses the field's metadata and cannot be customised.Both FieldSpec and CriterionSpec have Rename() methods like Command does (for calls like base.DefineField().Rename()).

  • [WEB] Lists in fields with few enough columns that they don't require the full available width will now fill it anyway.

  • [WEB] <EntityCriteriaView> no longer renders broken UI in Chrome when its columns contain different numbers of rows. This works because FieldGrid renders as display: grid or display: table based on browser detection.

  • [WEB] <BoxButton> icons are no longer invisible in Chrome.

  • [WEB] FieldContext has a new function RaiseFieldChanged(). If called by a field, this will cause the owner of the context to re-render its fields - for cases when something happening deep within a hierarchy needs to update the display of other parts of the same screen.

v234.5.0

  • [ORM] The.Values now supports two-way conversions between DateTime<->string and DateTimeOffset<->string, as well as their nullable versions.

  • [ORM] Improved performance of the dynamic (nongeneric) version of GetAll()/GetAllAsync() which() can be called from IEntityInfo or PersistenceManager. These queries now use the same freeze-by-cutoff mechanism as the generic GetAll<T>(), which avoids copying entire entity tables' IDs.

  • [WEB] <EntityBox> now supplies entity IDs rather than the entities themselves - it doesn't use the same IEntityContext as its parents, so this was dangerous.

  • [WEB] The public subclasses of CriterionSpec have been renamed to QueryCriterion and SpecificationCriterion. Previously there was a hierarchy of several classes differentiated only by generic parameters, which was somewhat confusing.

  • [WEB] Search criteria are now mapped to URLs, so searches can be linked or bookmarked. There are several pieces to this, each optional:

    * CriterionModels can now be serialised or parse a serialised value. This uses the Conversions infrastructure from The.Values, and you can supply traits for custom serialisation.
    * `<EntityCriteriaView>` accepts an InitialValues dictionary of serialised criteria - the keys are criterion labels.
    * `<EntitySearchView>` has a new bindable property QueryString, which builds serialised criteria from a URL query part. The QueryStringChanged callback is invoked when criteria are set in the UI or programmatically (including defaults).
    * The Browse page binds to QueryString, using NavigationManager to get and set the URI.
    

v234.4.0

  • [WEB] Improved appearance of non-text <Tooltip>s, with padding conforming to the design system. The padding or other styles can still be overridden by the application with the Theme property, which lets you provide a custom or built-in tippy.js theme.
  • [WEB] <AnonymousStatusView> and <CalculationControlView> have been improved and moved to The.Blazor.Shell. Neither requires its dependencies to be explicitly registered anymore (though you still need to be using The.Web to set AnonymousStatusView.IncludeClientDownload=true).
  • [WEB] Added <BoundDependency>. You probably don't need to use this in applications - it injects required-but-problematic dependencies from the container into its children, displaying an error if the service isn't present.
  • [WEB] Added <BoundProgress>, which also may or may not be useful to applications. It rerenders children on updates of an IProgress<Status>
  • [WEB] Added <ProgressBar>, which displays a meter optionally overlaid with text.
  • [WEB] Added two convenience methods to ScrollContext: ScrollToTopAsync() and ScrollToBottomAsync(). These are instructions to the innermost ScrollPanel which has cascaded the context.

v234.3.0

  • [WEB] Added <Tooltip>, a control which wraps its content with a popup tooltip which can be either text or an arbitrary component tree.

v234.2.0

  • [SQL] The AttributeColumns inside a PersistenceMetadataDictionary no longer have mutable flags. Please don't customise SQL output in weird ways.
  • [SQL] SQLEntityStore has a new optional parameter IEnumerable<AttributeInfo> insertAutonums. Attributes specified in this sequence will be inserted despite their autonum status, using SET IDENTITY_INSERT [table] ON. This will only work if insert triggers are disabled - it's for migration scenarios.

v234.1.1

  • [SQL] The AttributeColumns inside a PersistenceMetadataDictionary now have mutable flags, for customising SQL output in weird ways.

v234.1.0

  • [SQL] Migration now supports making a column an autonum. However, doing this in SQL Server will throw away its existing data - you need a custom datafix or migration process if you want to keep it somewhere (for example, try making the column Legacy and creating a new one).
  • [WEB] <ComboBox> option: OptionsQueryFactory. This alternate config parameter lets you control how the search is performed in more detail.

v234.0.1

  • [SQL] Added MigrationRunner.TryRunMigrations(), a variant of RunMigrations which provides the underlying error if migration failed. For backwards compatibility, RunMigrations() still exists and traps errors, but this will change at some point.
  • [WEB] Bugfix: <Checkbox> keyboard support was broken.
  • [WEB] <ComboBox> now selects on loss of focus if you've narrowed down your options to a single one by text filtering.

v234.0.0

  • [ORM] Added optional integration with IoC containers that conform to Microsoft.Extensions.DependencyInjection.Abstractions. The.Composition.Root has a HarvestDependencies() method which produces ServiceDecriptor entries; these don't represent the framework instance itself, but can instead be used to add the framework's own dependencies to a container.

    The EntityMetadataDictionary and Options are available, as are sub-dependencies of plugins. For example, when using SQLEntityStore, an IDatabase registration is available.

  • [SQL] Query translation now supports .ToString() on entities.

  • [WEB] AddTheScopedFramework() automatically registers The.Core dependencies in DI.

  • [WEB] Some Default___Spec classes in The.Blazor.Entities - the convenience base classes for UI scaffolding overrides - now have constructor parameters. These parameters are available in DI, so subclasses discovered by AddTheOverrides() just need a pass-through constructor.

  • [WEB] Added <BoxChrome>, a presentational component for making input widgets with a consistent frame.

  • [WEB] Added <ComboBox>, a custom selection widget which supports text-based search of a large set of choices. It can be used as an ISelectionWidget with a preselected set of options, but its true power lies in the ability to specify an OptionsQuery instead, performing database searches for the entered text.

  • [WEB] <LookupReferenceField> has been split into three versions: <LinkReferenceField> is a link or text (for reference data); <ListReferenceField> is the previous default version, which uses a <ListBox>; <ComboReferenceField>, the new default, uses <ComboBox>. DefaultEditSpec uses heuristics to decide which to display, and applications can override it.

  • [WEB] AddTheFramework() automatically registers The.Core dependencies in DI.

v233.4.1

  • Improved <LookupReferenceField> performance, though it's still only suitable for reference data type dropdowns.

v233.4.0

  • [ORM] Added ChangeNotification.AddDeepEntityChangedHandler, which notifies you of any changes to an entity's loaded graph (as long as you don't care what the change is).
  • [WEB] The "Save new object" command on Create screens is now just "Save".
  • [WEB] Commands can now have a CanExecute delegate, and save commands are enabled when entities NeedsSave().
  • [WEB] <EntityEditView> reevaluates command executability using DeepEntityChangedHandler.
  • [WEB] <LookupReferenceField> now respects modelled entity sort order.

v233.3.0

  • [WEB] CriterionSpecs may now have default values for their criteria. These values will be pre-filled into the search UI, but may subsequently be cleared.

v233.2.0

  • [ORM] The.Utility.CSVReader can now operate on arbitrary streams.
  • [WEB] Button components no longer allow linebreaks inside their label.

v233.1.1

  • [WEB] <StackingContext> (the layout component which resets sizing and positioning) now contains its children using overflow: hidden instead of width/height: 100%. This makes it suitable for use as a direct child of grid and flex layouts with other children - which is important, as it's used that way in <EntitySearchView>.
  • [WEB] The list-count overlay in the bottom right no longer uses transparency - it was clashing visually with scrollbars when those were present (which is unpredictable).
  • [WEB] <SectionField> (used for large fields like valuereferences and collections) now supports variable-height content with internal layout.

v233.1.0

  • [ORM] All IValues (attributes, references, boxes, lenses, etc) now implement INotifyValueChanged. This is a specialised variant of INotifyPropertyChanged for watching a single value's changes when you don't even care about its type - just the fact that whatever it was, it's different now.

  • [ORM] Added The.Values.ImmutableValue, a singleton value which cannot change and is always defaulted.

  • [ORM] Bugfix: DateProperty was broken in multiple ways, with at least four different methods to get non-date-only values into it. Existing databases which use date+time column types will in some cases contain some time data for supposedly date-only attributes.

  • [WEB] New scaffolding feature: entity search. The default Browse page displays search criteria based on ShowInSearch modelling, which are used to filter the list of retrieved entities.

    • Added <EntityCriteriaView> (and <DynamicEntityCriteriaView>), which displays search criteria for an entity type.
    • Added <EntitySearchView> (and <DynamicEntitySearchView>), which combines criteria and list views by rendering the criteria-generated query in the list.
    • Added ICriteriaSpec and DefaultCriteriaSpec, allowing applications to modify the search UI and queries.
    • Added <ExclusiveChoice>, a widget for picking one-of bool-valued things, and <InclusiveChoice> for picking zero-or-more-of. They're used to search for non-nullable and nullable booleans respectively.
    • Added <EntityBox>, an INullableWidget for picking from all entities of a type (primarily useful for reference data). Currently, criteria scaffolding is implemented for references and for the following attribute types: Date, Time, DateTime, Instant, Boolean, Integer, Long, Decimal, Currency, String, Text, Guid. We don't have built-in search ui for collections, BLOB, Version, File or Image.
  • [WEB] <BoxInput> is a wrapper around the primitive <input> tag, but it's also a widget in its own right, used to model strings. Accordingly, empty input boxes now produce a Value of null instead of "" if AllowNulls=true.

  • [WEB] PageService now has convenience methods for sending the user to scaffolded urls - for example, PageService.NavigateToEditPage().

v233.0.0

  • [MODEL] Attribute types are now listed in alphabetical order in dropdowns in the model editor.

  • [ORM] Autonum attributes of type long are now supported.

  • [ORM] Breaking: The type of ResultPool.Autonums has changed from Dictionary<Guid, int> to Dictionary<Guid, ValueBox>.

  • [REPORTS] The.Reports and The.Reports.Editor have been removed. They have been replaced by new packages Instagile.Reports and Instagile.Reports.Editor which are built and versioned separately.

  • [WEB] Extracted data-conversion and display code from The.Blazor.Fields.Attributes.___Field components into a layer of data-entry widgets which doesn't directly model IValues - they use Blazor's standard one- or two-way data binding. The new layer of components can be found in The.Blazor.Widgets.

    • New temporal components: <DateBox>, <TimeBox>, <DateTimeBox>, <InstantBox>.
    • New textual component: <MultilineBox>.
    • New enum-selection component: <ListBox>. <LookupReferenceField> now uses this to allow picking entities, and the previous display-only version is available as <ReadonlyReferenceField>.
    • New numeric components: <NumberBox> and <NumberTraitsBox>, which use The.Values conversions to/from text rather than built-in browser UI.
    • Renamed components: <FieldCheckbox>`` -> <Checkbox>, <FieldRadioGroup>`` -> <RadioGroup>, <FieldInput>`` -> <BoxInput>. <FieldFile> has also been renamed <FileButton>, but is not a Widget.
    • All widgets now bind immediately on user data entry, rather than on focus loss. (For example text fields use the oninput event instead of onchange). This means that changedness is visible without having to leave the field.
    • All widgets implement a commmon interface IWidget with a bindable Value property of an appropriate types and a HasChanges property which causes them to render a different visual state. Fields use this to display whether a property HasChanges(); in future we'll expand it to cover validity.
    • Many widgets also implement INullableWidget, which adds the IsNull and AllowNulls properties. These widgets are defaultable - unless AllowNulls is turned off, a .Value of null indicates that the user has not entered data at all.
  • [WEB] Improved <RadioGroup> to use custom styling like <Checkbox> (in fact, it's now somewhat better than Checkbox - we'll have to go back to that one).

  • [WEB] Added an IsSmall variant of <Checkbox>, like RowButton. This makes checkboxes about the same size as radio buttons, which can be useful when mixing them.

  • [WEB] Guids are now editable.

  • [WEB] <EntityEditView> now rerenders after an entity command is executed - for example, when a top-level entity is saved.

  • [WEB] Added <DynamicEntityListView> - the existing <EntityListView> has both a type parameter T and a Type parameter of type IEntityInfo. The "Dynamic" wrapper automatically determines the former from the latter, which is convenient in .razor files which don't have very sophisticated generics. This also improves performance for the Browse page, which was previously using IEntity-typed queries.

  • [WEB] The Entities parameter on both Dynamic and existing EntityListViews has been replaced with a Query parameter - lists perform dynamic paging and ordering on a query, rather than displaying a fixed set.

  • [WEB] <ColumnsPanel> has a new property SplitChildren. If set to true, child elements will be allowed to break across multiple columns.

  • [WEB] Added <RowsPanel> - like a <SectionPanel> without a header, padding or max width, embedded state, etc. <SectionRow> is now <PanelRow> and can be used in either view (or anywhere that expects potentially-labelled specified-height content). PanelRow has also been improved: it can no longer overflow the width of the section, and may instead scroll/wrap/trim internally if the field within it supports those things.

  • [WEB] The Create command on entity roots (Browse pages) no longer opens a new tab.

  • [WEB] Removed the virtual CreateQuery method on Browse pages - this was a failed experiment in overriding built-in pages by subclassing. Browse has a new optional BaseQuery parameter which can be used instead.

  • [WEB] Removed <ConvertedField> - <NumberBox> is a better version of the same thing.

  • [WEB] <EditPageLink>, <BrowsePageLink> and <CreatePageLink> now support passing through attributes to the underlying <a> (as do other 'primitive wrapper' controls).

  • [WEB] DefaultCommandSpec now exposes the built-in commands as overridable virtual methods. Commands have some new convenience copy-constructors for when you just want to rename them or change their behaviour without changing their name.

  • [WEB] <CollectionField> now has a ContentRows property which can be changed from the default, 5. Note that lists have a header, and a list row is 2/3 the size of an edit row - so the default actually provides for 6 list rows, (5-1 * 3/2). To get 12 list rows, you'd use ContentRows="9".

  • [WPF] login.dat is now stored in the user's local profile instead of their roaming profile. If found in the standard roaming profile location but not the local one, it will be moved.

v232.2.0

  • [OFFICE] ExcelSpreadsheet has some new features:

    • Call CreateExcelWorksheet instead of CreateWorksheet to get an ExcelWorksheet object which makes calling worksheet-modifying methods more convenient
    • SetColumnWidthInPixels performs the correct unit transformation from pixels to the mysterious OOXML units
    • SetRowHeight and SetRowHeightInPixels

v232.1.0

  • [WEB] ICommandSpec and DefaultCommandSpec<T> have a new method: DefineListCommands(). This operates on IQueryables, and lets you add or replace commands that apply to multiples of the same entity all at once. It can be used to remove/modify the Create command on default Browse pages, or to add commands that are applicable to top-level browsing and embedded collections.
  • [WEB] Built-in pages will now use a cascaded CommandContext if one is available, allowing command display to be hoisted or alternative UIs provided.
  • [WEB] Reminder (tasks) page can now have commands.
  • [WEB] Improved Browse page error handling.

v232.0.0

  • [SQLITE] Bugfix: Queries of the form

    Entity.Query(ctx).Take(0).Any()
    

    could fail, returning true instead of false! This was a SQLite bug, and has been fixed by updating our SQLite version.

  • [WPF] IWizard now implements IDisposable. WizardController will dispose of its wizard when it completes. Wizards built on WizardBaseBase can provide cleanup code by overriding OnCompleted.

v231.2.1

  • [EXTENSION] Improved template-generation's understanding of .NET 5 assembly structures. Running templates should now be more reliable on newer .NET versions and should leave less useless warnings in the log.

v231.2.0

  • [MODEL] Bugfix/feature: CreateEntityV2Event didn't support setting DefaultSort or DefaultSortDirection, and consequently ModelSnapshot.ToEvents() didn't preserve these values!

  • [ORM] OrderBy(PropertyInfo) and OrderByDescending(PropertyInfo) from The.Linq now support being called on IQueryable<T> which is statically typed as IQueryable<IEntity>, even when given a property existing only on runtime type T.

  • [WEB] AddTheEndpoint() has a new overload which supports constructing IRemoteAuthentications from an IServiceProvider.

  • [WEB] <ScrollPanel> now uses smooth scrolling by default. It can be disabled with a parameter.

  • [WEB] <ScrollPanel> provides a ScrollContext cascading parameter to its children. This can be used to retrieve a reference to the panel element, for direct control of scrolling.

  • [WEB] /Edit pages, when initially loading data, now use a layout that's similar to their eventual appearance - this reduces apparent flicker.

  • [WEB] <FieldInput> now has automatic styling for readonly inputs (previously provided at a higher level by <ReadonlyField>, which was hard to reuse).

  • [WEB] <SectionRow>s with Height > 1 no longer top-align their content (it's centered like other rows, and may fill the whole space if it desires).

  • [WEB] <ColumnsPanel> concludes its journey to a purely presentational component. Originally it had to produce its children from viewmodels using a RenderFragment<T>, because it needed to query them for their height. Now that the columnisation is done in CSS, it just takes direct content. Code like this:

      	<ColumnsPanel T="SectionSpec" Items="sections" Context="section">
      		<EditSection Entity="Entity" Section="section" />
      	</ColumnsPanel>
    

    Has changed to look like this:

      	<ColumnsPanel>
    
      	@foreach (var section in sections)
      	{
    
      			<EditSection Entity="Entity" Section="section" />
    
      	}
    
      	</ColumnsPanel>
    
  • [WEB] Added <FieldRadioGroup>, which generates labelled <input type="radio">s that, combined, model a selection from a list of options.

  • [WEB] New three-valued field UI for bool? properties;

  • [WEB] New multiline field UI for Text properties.

  • [WEB] New namespace The.Blazor.Fields.Attributes - this contains fields for every framework property type, which can be used in custom UI to produce inputs which match scaffolded UI. Previously, many properties were modelled as TextField<T> or TextField<T, U>, which is difficult to use in razor.

  • [WEB] Added <CreatePageLink>, the equivalent of <EditPageLink> and <BrowsePageLink> for Create.

  • [WEB] <EntityBrowseView> is now called <EntityListView> and all the subcomponents (like IBrowseSpec) have been renamed accordingly. Browse pages still exist; the idea is that in future these will become a combination of lists and search criteria, in the same way that lists are already embedded in Edit and Reminder pages.

  • [WEB] Improved button text display.

  • [WEB] Fixed bug causing /Edit pages with links back to themselves to duplicate the page's command buttons.

  • [WEB] <EntityListView> now respects the modelled default sort order for entities.

  • [WEB] Edit/List overrides are now simpler: when inheriting from the base DefaultEditSpec/DefaultListSpec, overriding field/cell definitions doesn't require you to also override the property binding. Each can still be done, but separately. FieldSpecs + PropertyBindings are aggregated into a SectionSpec, and the new CellSpec + its PropertyBinding are added to a ColumnSpec.

  • [WEB] Added ScaffoldService.ExtractSection(), which will give you a single SectionSpec that can be rendered using <EditSection>. This is useful for embedding parts of entities within each other, or within custom UI.

v231.0.1

  • [WEB] Further fixes to multi-row fields, particularly when nested.
  • [WEB] The built-in pages (/Browse, /Edit, /Create, /Reminder) now have top-level error handling and consistent display of runtime problems.
  • [WEB] Added <BoundFunction>, which is like <BoundTask> but for error-handling synchronous app code.
  • [WPF] Overriding Display screen models is now easier - the CreateUninitialisedModel override on controllers is passed more of the parameters it needs.

v231.0.0

  • [MODEL] There is a new Instant attribute type for recording moments in time. It is represented as the DateTimeOffset .NET type in memory, stored in UTC, and converted to the user's time zone for display and edit. This is as opposed to the DateTime attribute type, which refers to a calendar-and-clock measurement in an unspecified time zone. When migrating an existing DateTime attribute to Instant, modify MigrationParameters.AttributeConversionTimeZones to specify the time zone the DateTime values were recorded in, so that they can be converted to UTC correctly.

  • [MODEL] There is a new UseInstantForAudit model property, which must be set to True. Opening an existing .theModel file and saving it again will set the property. This property causes all entity createdOn and modifiedOn attributes to be Instant instead of DateTime. A migration is generated for this change which requires MigrationParameters.AuditConversionTimeZone to be set to the time zone the createdOn and modifiedOn values were recorded in, so that they can be converted to UTC correctly.

  • [OFFICE] The.MSOffice now supports .NET 5. Both Excel export and Access import are functional on .NET Core.

  • [ORM] PrimitiveAttributeBase no longer ignores overrides of its PersistenceValue property.

  • [ORM] IOwnedValue<T> was a structural but not a nominal superset of IProperty. It's now an actual subtype.

  • [ORM] The IValue.Convert<T,U> family of functions can now optionally be given convert-from/to functions as parameters, rather than using the predefined static conversions or Traits (which are also static).

  • [WEB] Better error handling for a number of field binding edge cases.

  • [WEB] Entity fields with labels may now be multi-row (previously only unlabelled fields could have height>1).

  • [WEB] SectionPanel uses a better indentation mechanism and can handle more-arbitrary row combinations.

  • [WEB] Added a new Options parameter DisplayTimezone, set by default to the local timezone's offset from UTC. This offset will be used to display and edit Instant properties in scaffolded UI.

  • [WEB] Fixed a bug changing nullable DateTime attributes which were null at the time of page load.

  • [WEB] PropertyBindings which produce IOwnedValues can now be Convert()ed (note that all IOwnedValues are IPropertys, but not all IPropertys are IOwnedValues).

  • [WPF] The.WPF now requires .NET 5 or .NET 4.6.1 (up from .NET Core 3.1 or .NET 4.6.1).

  • [WPF] ChangePasswordScreen now displays the required password strength level. It also once again always enables its "Change Password" button; if the entered password doesn't meet the required strength level then an error message will be displayed.

  • [WPF] Breaking: Surfaces can no longer be closed directly by application code; they're under the shell's control, and may include 'special' areas like a root surface or sidebar content. ISurface.Close() has been removed, and IServices.DestroySurface() has been added; this method is only guaranteed to work on surfaces created by IServices.CreateSurface(), which includes the surfaces given to screens in IScreenController.Display().

    In practice, this means you can destroy TabbedShell's tabs or Minishell's additional windows.

  • [WPF] The "save or discard changes" dialogs used on Create and Display screens have been redesigned. This is now part of an application shell; what the default TabbedShell will do is use the IModel properties to determine whether a screen has (valid) changes, calling a new method GetBlockingChangesAsync to find out which if any of those changes represent user input that should be reviewed before closing.

    Because this is now a shell feature, the API for screens is simpler: ISurface no longer has Push/Pop change-handler methods, and controllers no longer need to provide handlers or implement TryClose/TryRefresh functions.

v230.0.0

  • Building the framework now requires Visual Studio 2019 16.8.0.

  • [ORM] AsReadOperation() is now supported on unloaded collections.

  • [ORM] Added IFrozenQueryable().IsInMemory(), which can be used to check whether a query (including collections) is fully or partially loaded.

  • [WEB] The.Blazor now requires .NET 5 in order to use new Blazor features.

  • [WEB] Components are now themeable via pure CSS, with no need to control layout partially in the backend and partially in the frontend. The number of theme variables has been reduced, since targetting individual components provides better control; for example, instead of setting root variable --the-column-width: 500px to affect <ColumnsPanel>, you can write something like

    .the-columns-panel {
      column-width: 500px;
    }
    

    This change should also simplify custom component creation because there are fewer variables for apps' components to support.

  • [WEB] Entity pages now use outlining - h1, h2, h3 tags - to improve accessibility.

  • [WEB] <EntityBrowseView> now uses virtualised scrolling and can handle large datasets (tens of thousands of rows without index, millions of rows if appropriate indexes are in place). When loading data from a database (as opposed to in memory collections), reference cells and collection counts will be preloaded in the same query batch via a single database roundtrip.

  • [WEB] <CollectionField> has supports reactive rerenders when its contents change and supports the use of multiple entitycontexts (the new contents may be in a different context, for example).

  • [WEB] <EntityBrowseView> and <CollectionField> are now generic with a type parameter T. This is inconvenient, but more efficient - LINQ queries don't have to cast everything to and from IEntity inside the components. We'll reevaluate this tradeoff over time.

  • [WEB] Fixed <EntityBrowseView> header heights in Chrome/Safari.

  • [WEB] Fixed <ReferenceCell> bug when rendering minimal diffs.

  • [WEB] Improved error handling and display for <CommandButtons>, <ColumnsPanel> and list cells.

  • [WEB] <ColumnsPanel> has a new optional ColumnCount parameter. If none is set, the column count will be derived from available width.

  • [WEB] Added <SectionPanel>, an entity-agnostic control which provides the ui for EntityEditView sections. A SectionPanel displays a header and rows of indented content, which can use grid span properties to eschew labels or cover multiple rows. Optionally, the rows can be <SectionRow> components, which abstract those features and are used for EntityEditView properties.

  • [WEB] <FieldInput> has specialised appearances for more input types. In general, you should use <FieldInput> instead of <input> by default in The.Blazor apps, dropping down to <input> only in order to opt out of the themed widget look.

  • [WEB] Added <FieldCheckbox>, which is conceptually similar to <FieldInput> but uses even-more custom UI instead of an <input type="checkbox"> tag - those are difficult to style consistently across browsers.

  • [WEB] Added <FieldFile>, which wraps the builtin <InputFile> but gives it the appearance of a RowButton. (<InputFile> is in turn a wrapper for <input type="file">, which has an unstyleable UI).

  • [WEB] <RowButton> and <CommandButtons> can now be "small" (IsSmall=true) to indicate that they're being used in the 2-unit rows used by denser ui than the standard 3-unit rows.

  • [WEB] Added visually-disabled styles for buttons (RowButton, input type="submit", etc) when the html disabled attribute is set.

v229.3.1

  • [IMPORT] Import sources now specify how they compare table and column names (e.g. case-sensitive or insensitive) and this choice is respected by import.

v229.3.0

  • [OFFICE] AccessImportSource used to tolerate composite primary keys as long as there were no foreign keys to them, but no longer did after multi-valued column support was added. It should now once again tolerate these keys on tables with no multi-valued columns.

  • [ORM] Added support for IQueryable<IEntity>.Select(RelationshipInfo metadata) - previously you needed to use an IQueryable<T> where typeof(T) == metadata.Parent.EntityType.

  • [ORM] The.Linq now supports nulls within entity-enumeration queries. In practice, these will only be produced with .Select() calls, like

    Foo.Query(context).Select(f `=>` null as Foo), or
    Foo.Query(context).Select(f `=>` f.Bar) // where not all Foos have a Bar
    

    Although DataContractEntityStore could execute these queries, previously you'd get a NullReferenceException when reifying them.

  • [SQL] Improved support for linq Distinct(). In the initial implementation, this applied a DISTINCT clause to the final SQL output no matter where the operator appeared in the query - clearly wrong for anything involving .Select() or .SelectMany(). Now there's partial tracking of what exactly is and is not distinct.

  • [SQL] Added support for null checks and null coalescing within .Select() calls that project to non-entity values. This was the original motivating query, from NPS:

    Entity.SuppliedItems.Take(5).Select(x `=>` x.InventoryItem == null ? string.Empty : x.InventoryItem.Text)
    

    It was running up against core bugs (QIR generating needless INNER JOINs) as well as inadequate DML generation (needing a nontrivial GROUP BY clause). The generated T-SQL is alarming, but acceptable: SELECT TOP(5) IIF(T2.[ID] IS NULL, @p0, T3.[Text]) FROM [dbo].[ItemSupplier] T0 INNER JOIN [ItemSupplier_2_TradingEntity] JT0_T1 ON T0.[ID] = JT0_T1.[ItemSupplier_ID] INNER JOIN [TradingEntity] T1 ON T1.[ID] = JT0_T1.[TradingEntity_ID] LEFT JOIN [TradingEntity_2_InventoryItem] JT1_T2 ON T1.[ID] = JT1_T2.[TradingEntity_ID] LEFT JOIN [InventoryItem] T2 ON T2.[ID] = JT1_T2.[InventoryItem_ID] LEFT JOIN [TradingEntity_2_InventoryItem] JT1_T3 ON T1.[ID] = JT1_T3.[TradingEntity_ID] LEFT JOIN [InventoryItem] T3 ON T3.[ID] = JT1_T3.[InventoryItem_ID] WHERE T0.[ID] = 'fa7881e0-3e7a-4650-ab1e-bfe20d1a7e70' GROUP BY T1.[ID],IIF(T2.[ID] IS NULL, @p0, T3.[Text])

  • [SQL] Added support for queries that produce null or duplicated entity values. Previously, entity returns were implicity treated as a set, with DISTINCT or GROUP BY used to guarantee uniqueness and cardinality reduction instead of nulls. Now it's possible to load, count or otherwise query datasets where some but not all entites are present. This feature is useful for adding loads of directly related entities to existing complex queries.

  • [SQL] Improved the implementation of aggregation functions Count(), Min(), Max(), Average(), Sum(). These now support the full range of query features which were available to enumeration functions like ToList().

  • [SQL] Corrected the implementation of .All(f), which behaved very oddly when you also used a .Where() clause.

  • [SQL] Bugfix: SQL Server was translating string.Length, which is of type int, to a 64-bit value. This was ok for comparison in Where(), but it would blow up aggregations like Sum().

  • [WEB] Added <ActionLink>, which renders a non-navigation anchor tag that executes code when clicked (works with Action, Func<Task>, etc).

  • [WPF] Bugfix: Errors from async commands added using AddCustomCommand could be swallowed.

v229.2.0

  • [SQLITE] SQLite isn't async internally, but SQLiteEntityStore now deliberately yields its thread on ExecuteReads() and ExecuteWrites() calls so that UI layers have time to draw progress bars and similar.

  • [WEB] The.Blazor now comes with a set of top-level page components for generic entity UI. These can be used as a whole via the Router.AdditionalAssemblies property, or wrapped in app-specific pages by subclassing or using ordinary component syntax. Here's an example of wrapping the /Browse page to change its URL and add a default:

    @page "/prototype/browse"
    @page "/prototype/browse/{type}"
    @code {
      [Parameter] public string Type { get; set; }
      protected override void OnParametersSet()
      {
      	if (Type == null) Type = nameof(Human);
      }
    }
    
      <The.Blazor.Pages.Browse Type="@Type" />
    
  • [WEB] Added <HeaderPanel>, which presents its first element as a header and the rest as equal-height rows in a fixed-size context (so if there is only one remaining element, it fills the space). This panel is used by the built-in pages to provide a command bar and internal scrolling, like so:

      <HeaderPanel>
      	<TitleBar Title="Some Entities" />
      	<EntityBrowseView Type="@type" Entities="@entities" />
      </HeaderPanel>
    
  • [WEB] <HScrollPanel> replaced with <ScrollPanel>, which supports configurable scrolling in either or (by default) both directions.

  • [WEB] Added error handling for command bindings (which can be defined in application code via ICommandSpec).

  • [WEB] Improved performance when switching between urls which render the same page - in some cases this process was using <BoundTask Binding="SomeMethodGroup">, which defeats the Blazor diff algorithm. When overriding the built-in pages, take care to use a @key attribute derived from URL parts. Example:

      <HeaderPanel>
          <TitleBar Title="@type.PluralCaption" />
          <BoundTask @key="type" Binding="LoadEntities">
              <EntityBrowseView Type="@type" Entities="@context" />
          </BoundTask>
      </HeaderPanel>
    
  • [WEB] Bugfix: On Firefox, ColumnsPanel could break columns inside a section.

v229.1.1

  • [WPF] Bugfix: Using UseIntegratedPasswordLogin would lead to an ArgumentNullException being thrown and caught within the framework during composition unless the caller also turned off "automatic login" in the The.WPF options (not the same thing as the allowAutomaticLogin parameter).

v229.1.0

  • [WPF] LSCF can now also be constructed with additional commands, like LVSCF and GVSCF.

v229.0.0

  • [WPF] LVSCF and GVSCF can now be constructed with additional commands that will be displayed alongside their add command.
  • [WPF] Breaking: AddButtonText can no longer be overridden on LVSCF or GVSCF. To change the add button text please override addCommand with a different name.

v228.0.0

  • [ORM] ObservableCollection.AddRange() extension method. This is for convenience, not performance - it still dispatches multiple add events.

  • [ORM] Added IOwnedSet<T> (no relation) as a collection analogue of IOwnedValue<T>. EntityReferenceProperty is now an IOwnedValue<IEntity>, and EntityCollectionProperty is an IOwnedCollection<IEntity>; this provides nongeneric accessors for relationship properties, similar to the ones attribute properties already had.

  • [ORM] Added IUpdateService which represents autoupdates available in a transport-agnostic way.

  • [WEB] Framework authentication now works via standard blazor mechanisms without needing to wrap content in a PrincipalView (which has been removed).

  • [WEB] Initial implementation of a design system resembling The.WPF's "Inky". Inky for web covers some metrics, colours and conventions which, if followed, should make apps consistently themeable with a reasonable default appearance.

  • [WEB] Added a variety of reusable controls:

    • <BoundTask> defers rendering while loading.
    • <BoundLink> presents links based on dynamic data (LinkModel).
    • <ClientLink> uses the new IUpdateService to provide a link to download a desktop application.
    • <RowButton> is a themed and fixed-height command button.
    • <FieldInput> is a themed data-bindable form-input wrapper.
    • <InlineRichText> can render a graph created by a RichTextBuilder into text runs and dynamic links.
    • <DebugChrome> represents design-time "programmer error" - the visual equivalent of an exception.
    • <ErrorChrome> provides the backdrop for run-time "expected" errors - potentially user-visible problems.
    • <BarChrome> provides the appearance of headers and linkbars.
    • <TextPanel> embeds flow-layout text (and other inlines) into a box-model layout (flex or grid).
    • <HScrollPanel> gives its contents a horizontal scrollbar.
    • <ColumnsPanel> lays out its contents in vertically-packed columns of a constrained width.
    • <AnonymousStatusView> is a full page view similar to the handwritten status pages we've been putting in our backend apps.
    • <CalculationControlView> replaces <CalculationControl>.
    • <RemindersView> displays a list of preset search links using The.Core's IReminders, similar to The.WPF RemindersSidebar.
  • [WEB] New entity UI architecture. <EntityEditView> constitutes the bulk of an edit "page" (but does not have to be used as one); pair it with a <TitleBar> in a cascading CommandContext to create something very similar to The.WPF's Display screen or Create screens. <EntityBrowseView> displays an internally scrolling columnar list similar to List and top-level WPF screens.

    ScaffoldService is used to generate the screen layout and PageService provides links between entity pages; commands and pages can be customised with overrides which either subclass Default____Spec or implement I___Spec directly. Similarly, EditSpec and BrowseSpec allow applications to customise or replace the scaffolding of fields and columns. Overrides can be registered using a services builder or in DI; AddTheOverrides() will discover them automatically.

  • [WEB] Added entity-specific controls and primitives:

    • <BoundValue> and <BoundProperty> to defer rendering scaffolded UI.
    • Reusable sub-parts of entity ui (for example, <SectionWithHeader>) in The.Blazor.Entities.
    • Many edit-field and browse-cell types in The.Blazor.Fields.
  • [WEB] Added <GridShell>, a customisable application layout based on a central content area and optional customisable side parts.

  • [WEB] UpdateService implements IUpdateService and can be used outside of controllers. UpdateControllerBase consumes it.

v227.1.1

  • [WPF] DisplayController bugfix: saving became deadlocked when two parts of the process attempted to use the screen model's "IsLoading" flag in a reentrant fashion.

v227.1.0

  • [ORM] SavePlanner now detects and reports some forms of invalid graph, including Deleted/Deleting entities which are being inserted into a relationship (foreign key violations) and entities in Deleted state which have made their way into the connected tree (generally be due to an application bug like:)

    var entity = new Foo(context);
    foo.Bar = "important value";
    foo.Delete();
    foo.SaveAsync();
    
  • [ORM] As an exception to deletion not automatically pruning, IEntity.Delete(/* no arguments */) on a never-saved entity will break relationships. This doesn't require lazy loading since all of its relationships are in-memory. You'll get an error when using this pattern:

    var deletedBar = new Bar();
    deletedBar.Delete();
    foo.Bar = deletedBar;
    

    But not for this pattern: foo.Bar = new Bar(); foo.Bar.Delete(); This behaviour is also available through EntityKernel.PruneLoaded().

  • [SQLITE] DateTime attributes were incorrectly stored in UTC, causing their values to change when loaded in a different time zone to the one they were saved in.

  • [WPF] DisplayController.SaveAsync() no longer traps errors internally. The screen still does so when you save it, but if application code calls the method then exceptions will propagate to the application.

v227.0.0

  • [ORM] There is a new core option ReplaceSmartPunctuation, which causes various non-ANSI dashes and quotation marks ("smart quotes") to be replaced with ANSI-friendly approximations when they are in strings assigned to String and Text attributes.

v226.1.0

  • [WPF] Display and Create modal controllers can now store and restore their vertical scroll position.
  • [WPF] There is a new extension method ISurface.StoreCurrentModalScrollPosition which should be called before calling ISurface.PushModalContent.

v226.0.1

  • [WPF] Bugfix: ListController would prevent its tab from closing if its model HasChanges, even though it is unsavable.

v226.0.0

  • [WPF] Improve responsiveness of screens with lots of lists by making VirtualisedList use a mostly async synchronisation object rather than AutoResetEvent.
  • [WPF] Bugfix: ScreenControllerBase.Replace would not clean up any existing screens on its surface.
  • [WPF] Breaking: ISurface now has an event ContentChanging which is called before the content on that surface is replaced.

v225.1.0

  • [ORM] IEntitySet now has ClearAsync which will not block on loading a collection in order to clear it.
  • [WPF] Bugfix: ChangePasswordScreen incorrectly compared its minimumPasswordStrengthScore parameter to a score between 0 and 1, making it unreasonably difficult to satisfy.

v225.0.0

  • [OFFICE] ExcelSpreadsheet now supports cell formats with wrapping text.

  • [ORM] Changed the semantics of deletion, for correctness and to remove a cause of lazy-loading. The following methods are now available on IEntity:

    • Delete() marks the entity itself for deletion; it does not break any relationships. This should be used in business logic which wants to be deliberate about what changes are made.
    • DeleteAndPruneAsync() marks the entity for deletion, and also removes it from its relationships. This version is async because it may have to load some relationships in order to clear them.
    • DeleteAndCascadeAsync() is a higher-level operation which transitively marks the entity and its owned (Value-navigation) children. It will break ("prune") non-value relationships as well. All of these operations use the EntityKernel primitives MarkDeleted() and PruneAsync(), which are accessible if you need full control.
  • [ORM] Removed AccessEntityStore. We still have AccessImportFormat, but no longer support using a JET db as the backend for a framework app.

  • [ORM] Bugfix: If you loaded an entity with a many-to-many relationship into two contexts, added a child entity to the relationship in context A, saved context A, then cloned the version of the entity from context B over context A, a NullReferenceException was thrown internally. An app did this by accident; there are now unit tests in case we someday do it on purpose.

  • [ORM] CSV import now ignores columns with no name and no data, and rows with no data.

  • [SQL] Errors from query translation are now structured, containing information about the nature of the failure and the typed query fragment on which it was operating. These are either programming errors in the framework (detected by pre/postconditions within the translator code) or in an application (making use of LINQ features which we don't support); in both cases, the error can turn up very far from its point of origin, so it's worth giving developers some help debugging.

  • [WPF] Now that it's possible to specify non-datastore queries, Search and Criteria screens are available for transient entities. (Previously, the generated ControllerFactory would throw an exception).

  • [WPF] Applied DeleteAndCascade semantics to more fields. Previously this was inconsistent - ListValueCollection and GridValueCollection deleted value-children-of-value-children, but ValueSectionedReference and ValueInlineReference did not. This was unexpected and sometimes led to 'orphan' entities littering databases.

  • [WPF] Users are now given an indication of password strength when changing their password. Applications can choose the minimum password strength level (between 0 and 4 inclusive).

  • [WPF] UseIntegratedPasswordLogin has a new parameter for a logger to use when attempting autoupdate, and a new overload which takes a The.Composition.Root parameter and uses it to populate the application name and environment and the autoupdate logger.

  • [WPF] Closing an application and closing a tab now both invoke the same controller extension point, OnClosingFromShellAsync. This method will be called on each screen being closed and each of its modals (last-opened first), and each callee has an opportunity to cancel the close.

  • [WPF] IScreenModel.CloseCommand is now CancelCommand and is only relevant for modal screen models.

  • [WPF] Value collection fields' Remove button now says Delete instead.

  • [WPF] Resize "grips" (actually GridSplitters) for sections and multi-line text fields are now more obviously grippable.

v224.2.1

  • [REPORTS] Bugfix: When editing raw RTF in ReportEditor, particularly weird RTF-logical-structure errors could render the input pane unresponsive. These errors are now trapped and the editor can recover.
  • [REPORTS] Bugfix: Viewing raw RTF in the output pane didn't work for complex documents.

v224.2.0

  • [WPF] CreateProperty() on WizardBase has been renamed to Bind(); the renaming is because its semantics have changed. The created IValue will, by default, affect validity of a page but not the next wizard-steps possible. Both flags are configurable.
  • [WPF] IWizard<T>.OnFinishing now has a "T result" parameter which contains the value the wizard will return.
  • [WPF] Fixed the titleFallback parameter on some WizardController constructor overloads not functioning.
  • [WPF] List row commands now support grouping.

v224.1.0

  • [WPF] Bugfix: discovery of controller overrides was broken for Create, Criteria and Search screens.

  • [WPF] Now that Create and CreateModal screens may have async loading, they need new lifecycle hooks. Added:

    • OnCreated/OnCreatedAsync, which run once the entity is constructed and initialised. This is after OnModelCreated (which refers to the Create screen's model), but before the Content sub-controller is created.
    • OnLoaded/OnLoadedAsync, which run after the Content sub-screen is displayed and the UI is ready for interaction.
  • [WPF] Create had a protected Entity property, but CreateModal did not; now it's there on both.

v224.0.1

  • [WPF] Bugfix: AdminUserProfileSearchBehaviour did not actually add any commands to user profile search screens.

v224.0.0

  • [MODEL] Templates now include a header which marks the file as generated in a way the compiler/IDE recognise. This improves build performance and prevents the reporting of a bunch of unactionable messages from generated source files.

  • [MODEL] Bugfix: The 'Extract as reference data' command would not mark the extracted attribute(s) as nullable, which could lead to an error when you try to save.

  • [ORM] Entity specs can now be created with a base query function, bringing them a little closer to the LINQ world.

    Old (still works): Foo.Specify() New: Foo.Specify(Foo.Query) - or Foo.Specify(context => someFooSource(context).Where(myComplexQuery)).

  • [ORM] The finalizer on frozen queries (which exists to try and clean up database rows if you didn't dispose them) is now even more fire-and-forget - it sends off an async operation to the datastore and doesn't even attempt to wait for it. Since it was running in a finalizer, it's not like it could observe exceptions anyway...

  • [ORM] EntityMetadataDictionary is now case-insensitive. Services.Entities["businessobject"] will return the same IEntityInfo as Services.Entities["BusinessObject"].

  • [ORM] IServices now has AppVersion and AppName properties alongside the existing Version property. These are derived from the entry-point assembly, but can be overridden in Options.

  • [ORM] The.Values type conversions now support bool and bool?.

  • [ORM] The semantics of IEntity.Delete() and EntityKernel.MarkDeleted() have changed... again. Deleting entities and breaking their relationships are now two separate kernel methods (MarkDeleted and RemoveRelationshipsAsync).

  • [WEB] .AddHostedService is now AddTypedHostedService, so that it's clearer that it has different behaviour to the built-in version. There are also several more overloads available.

  • [WPF] AddRowCommandListBehavior and AddRowCommandGridBehavior now support async commands.

  • [WPF] Criteria and Search screens have a new optional parameter (available through ScreenService overloads): Func<IEntityContext, IQueryable<T>> queryFactory

    If provided, this query [factory] is used as the base set within which to search. It doesn't have to be a database query, so you can now use search screens on in-memory collections! To achieve that, supply a factory like "_ => list.AsQueryable()".

  • [WPF] The Reminders sidebar controller can now be configured to use Search instead of List screens. For backwards-compatibility, the default is unchanged, but we might invert that in the future.

  • [WPF] Create screens can now take an async initialiser or async entity-factory function.

  • [WPF] The Agile Computing Pty Ltd code signing certificate timestamp server URL has changed.

  • [WPF] List and Grid screens are now overlaid with "(1 item)" instead of "(1 items)" when there is, in fact, 1 item.

v223.0.1

  • [LINQ] Using Freeze() on a queryable that's been cast to IQueryable<IEntity> (or other base type, like component interfaces) now produces frozenqueryables that can be cast back to their concrete entity type. This is useful when doing nongeneric programming using IEntityInfo - for example, the following line now works:

    someMetadata.Query(context).Freeze().ToList()
    

    Previously, you would have had to write

      someMetadata.Query<T>(context).Freeze().ToList()
    

    with T set to a concrete entity type.

  • [LINQ] Nongeneric methods like PersistenceService.CreateQuery or IEntityInfo.Query() now reliably create concrete-type queries that have been cast to IEntity queries but which can be recovered (using visitors, out-of-band type knowledge, etc).

  • [LINQ] DataContractEntityStore, unlike SQL, did not support queries of the form

    `MyUserProfile.Query(ctx).Cast<IUserProfile>().Where(p`` =>` p.DisplayName == "Foo").Freeze()
    

    It worked as long as you started with the abstract profile type, but mixing and matching wasn't possible.

  • [WPF] The.WPF.Screens.Display.CountsCacher is now public - this is just a utility visitor that stores GetAll() sets in a context. Apps that want to recreate some of what Display screens do internally want access to it, since that used to be an (unadvertised) feature of DisplayController itself.

v223.0.0

  • [ORM] Breaking: IEntityContext is now in namespace The instead of The.Entities. Like IServices, it gets shadowed by higher layers (The.WPF, The.Web, The.Blazor). When writing code that targets one of these four compositions, you should have a using statement (or viewimports) for exactly one of the four core namespaces.

    From an app development POV the main feature of a shadowing context type is that it gives you access to the shadowing services type, but they also provide an important check for some subtler semantics: different layers have different lifetimes for their components, and using the context type specific to a layer prevents accidental use of a component with the wrong lifetime. For example:

    • The.WPF.IServices is guaranteed to last as long as a WPF Dispatcher itself, so The.WPF.IEntityContext can be long-lasting; The.IServices in the core can be disposed, and its contexts should be considered owned.
    • The.Web.IEntityContext is scoped to an HTTP request, while The.Blazor.IEntityContext is transient, representing part of an SPA page. These aren't things you'll have to think about when writing an application (or working on the framework) because the incompatible context types make it impossible to get it wrong.
  • [ORM] Breaking: WebEndpoint, the main IEndpoint implementation used with RemoteEntityStore, was designed with a flawed understanding of URL concatentation. It worked like the HTML <base> tag, not the way that the RFC - and HttpClient - work. This made it difficult to reuse HttpClient instances and access entitystore backends at sub-paths of domains. Relative path concatenation and BaseUri now work according to RFC 3986:

    • If your HttpClient is only for accessing persistence, set the BaseAddress to the full endpoint path.
    • BaseAddress should always end with a slash - "https://server/endpoint/", not "https://server/endpoint".
    • If it's used for other endpoints on the same server (for example autoupdate) and you supply the persistence endpoint as a path fragment, change it from an absolute path ("/endpoint") to a relative one ("endpoint/") - unless for some reason you want to point to the root of the server.
  • [ORM] Remote authenticators can now support credential push - rather than passing in a get() function to PasswordAuthentication, you can set the username and password later (e.g. once the user has entered them).

  • [WEB] Breaking: The.Web now requires .NET Core 3.1 (up from 2.1).

  • [WEB] Breaking: AddTheProxy() is now AddTheEndpoint() (that's what it does, register an IEndpoint).

  • [WEB] Setup of core framework deps & options can now be done fully builder-style - you can write .AddTheFramework().RegisterAuthorisation().Configure().

  • [WEB] New composition method AddHostedService<TService,TInterface> for creating background services with a public interface (accessible to both HttpContext and Blazor Server app models). This one isn't AddThe because it's just a convenience overload of existing ASP.NET Core methods.

  • [WEB] New controller The.Web.Security.AccountControllerBase. It has Login and Logout methods for simple password-based server-side login - this is for using Identity without the default UI.

  • [WEB] New package The.Blazor replaces The.Web.Components. It requires .NET Standard 2.1. It does not depend on The.Web, and vice versa - they're totally independent. In a webapp without Blazor you will use only The.Web, a Blazor WebAssembly app will have only The.Blazor, and a Blazor Server app may use both (if it needs server-side features like running a RemoteEntityStore endpoint).

  • [WEB] The.Blazor has its own IServices and IEntityContext, which are deliberately incompatible with The.Web (but both are subtypes of The.Core's versions). In practice, this means that you should @using The.Web in _ViewImports.cshtml or @using The.Blazor in _Imports.razor. It's ok to mix both of those in a single project.

  • [WEB] For composition, The.Blazor has AddTheScopedFramework methods similar to The.Web's AddTheFramework methods. As the name implies, the Blazor version is scoped to a user's session and cannot be used from Singleton-lifetime services; it has no access to a HttpContext but can, obviously, use Blazor features.

  • [WEB] Authentication in The.Blazor has several options. Blazor Server can use ASP.NET server-side authentication, with cookies and optionally Identity. The framework integrates with this just as it does in The.Web (but the internals are different). But what if you don't want to UseAuthentication(), or you have a pure client-side app with no backend at all?

    In this case you technically aren't doing authentication at all - the client is static files - and Blazor provides a few authorization mechanisms, such as UseApiAuthorization() which integrates with IdentityServer. The.Blazor will also integrate with those if one is used. Finally, there's the option of using the framework's own remote authentication mechanism. Call AddTheScopedFramework with an IRemoteAuthentication and an endpoint (or the address of one), and The.Blazor will implement Blazor's AuthenticationState features (Cascading authentication state, AuthorizeView, AuthorizeRouteView) in terms of that authenticator. This doesn't require ASP.NET Core in any form, but because no backend is involved it can't use cookies to save your login! It could be good for SSO intranet apps, or for fixed-function sites which communicate with a backend using a shared secret or API key - and perhaps we could implement login-saving with LocalStorage.

  • [WPF] Introduced The.WPF.IEntityContext. Wherever screens and services were using The.IEntityContext, they now consume or provide the shadowing version instead. The.WPF.IServices creates WPF contexts instead of Core contexts, and these use the logged-in (or -out) principal from SessionService.

v222.3.0

  • [WPF] ContentController, GridController and GridRowModel now provide a protected ChangeExecutor or SharedChangeExecutor which can be used with ChangeNotification. This allows subclasses to enroll extra property paths for custom reactions to deep changes, using the deduplication and async-execution features of NotificationExecutor.

v222.2.2

  • [MODEL] EphemeralVersion events' timestamps are now formatted consistently when converted to version names in ModelSnapshot. This should prevent some churn when generating templates in different environments.

v222.2.1

  • [MODEL] Fixed a model-upgrade bug converting events like CreateAttribute(1, "A", Decimal, MaxLength = 39) to new ones with a shorter MaxLength.
  • [ORM] NotifySaving[Async]() is now called before any properties are calculated during a save. This can be useful for, for example, performing batch loads of data necessary for calculation. Since during-save calculation was unpredictable in the old implementation, it wasn't possible to guarantee this.
  • [ORM] OnSavedAsync() and OnSavingAsync() are also guaranteed to be called before the sync variants, for the same purpose of preloading.
  • [ORM] DataContractEntityStore now emulates SQL NULLs for joins through references - you can query foo.Bar.Baz where foo.Bar is null, and get null back in return.

v222.2.0

  • [MODEL] The model editor now has add-, edit- and remove-tag commands in various places.
  • [MODEL] WPFEditor now recognises system shortcuts for dialog buttons in its popup dialogs (e.g. enter for 'OK' buttons and esc for 'Cancel').
  • [MODEL] Fixed a model editor bug creating new Currency attributes.
  • [MODEL] Fixed a model-upgrade bug converting sequences like CreateAttribute(1, "A"), CreateAttribute(2, "A"), ChangeAttribute(2, "A2") in which the two attributes temporarily had the same name.
  • [ORM] Attributes with modelled Precision are now rounded consistently in-memory, when calculated, and in the datastore. For Decimal and Currency attributes this means the .NET default of banker's rounding (half-even). The various rounding scenarios are tested and will be kept consistent so that apps don't have to manage their own precision (for standard use cases).

v222.1.4

  • [WPF] The UserProfile component now uses a Create screen to Create profiles instead of pre-saving them and opening a Display screen.
  • [WPF] ListController.Open is now overridable, allowing subclasses to do something other than open the selected entity.

v22.1.3

  • Bugfixes.

v222.1.0

  • Release builds now require Eazfuscator.Net version 2020.1. All produced nupkgs are now obfuscated.

  • [MODEL] New ModelFile version 8, with new events CreateEntityV2, ChangeEntityV3, ChangeAttributeV8. Only the new events can now be used to set calculation modes, and subclassing has been removed (it's still in snapshots built from older models, but the new events cannot set Superclass or IsAbstract).

  • [MODEL] Event obsolescence is now versioned - events are deprecated from a particular version onward, rather than generally.

  • [MODEL] ModelFile now supports version pinning; if you set a max version in the constructor, events will only be upgraded to that version and no further. Saving models at a particular version will audit the history for incompatible events (ones that are too new for the runtime version you're anticipating); this is a breaking change.

  • [MODEL] Fixed bug where errors while saving a ModelFile to disk (as opposed to memory or into a stream) could overwrite the destination with an empty file.

  • [MODEL] The WPF HistoryEditor control has a new property, MaxVersion. If set, this will be passed though to the editor controller; you can see the effective model version on the app node. The.Extension tries to load a max supported version from the solution's references, in the same way it uses the referenced runtime to run code generation.

  • [MODEL] Added The.Model.EventFactory, which generates correctly versioned events based on the max model version you want it to use.

    Putting the pieces together, this means that the editor in the Instagile extension, if used to open a .theModel in a .sln with Framework 222 or lower, will set MaxVersion to 7 instead of 8. The model file will use version pinning, and it won't be able to save v8 events, which would be incompatible with the application's templates and runtime. Instead it will generate different events; ones appropriate to the runtime you're targetting.

  • [SQL] MigrationRunner now traps exceptions, meaning that RunMigrations() can complete without actually running them. It returns a signal value if this occurs, but there won't be much most apps can do about it; the point is more to prevent exceptions from hitting the top of the stack in Startup.Configure, which behaves very poorly in ASP.NET Core. In particular, it tears down the site before you can actually see the logged error!

  • [WPF] Theme bugfix: PasswordBox had inadvertently been made IsTabStop=False in Inky. This was a problem for LoginWindow in particular.

  • [WPF] List bugfix: Reused cells were keeping the overridden background from other entities that had been in the same row.

v222.0.0

  • This release contains breaking changes to how calculated properties work. Brief update guide:

    1. Remove your [Calculated] attributes and set calculation modes in the model editor, using OnDemand for properties that don't need async data access and OnSave for properties that do.
    2. Set entity Text calculation in the editor, choosing "Simple format string" for entities without overridden GetText() and "Programmed calculation" if you have (and want to keep) an override.
    3. OnSave properties will no longer be 'temporarily live' before their first save, so change any application-specific business logic which expects that to be the case. If you need to calculate a property without saving it, call EntityKernel.CalculateAsync() or AttributeBase.CalculateAsync().
  • [MODEL] Attributes now have a CalculationMode property, applicable only to attributes with IsCalculated=true. The CreateAttributeV5 and ChangeAttributeV7 events can be used to set CalculationMode, which defaults to OnSave. The model editor will show a dropdown for CalculationMode when an attribute IsCalculated.

  • [MODEL] Entities have a TextCalculationMode property for their synthesised Text. It works the same way as attribute TextCalculationMode, but defaults to OnDemand.

  • [MODEL] Entities have a new IsTextCalculated property as well. Technically, .Text is always calculated, but it can be generated from the DisplayFormat string; only if IsTextCalculated is set will actual abstract methods now be generated.

  • [MODEL] In the editor, each node type combines the CalculationMode and IsCalculated property. Entity nodes use a single dropdrown to select formatted/overridden and sync/async, and attribute nodes have a three-way dropdown for not calculated/sync/async.

  • [ORM] Calculation modes and behaviour have been simplified. They should now be easier to reason about, with fewer unexpected null reference exceptions and unexpected lazy loads, but there's less helpful "magic". The new modes are OnDemand, OnSave and Manual; the first two are similar to the old Live and OnSave modes; the third one means that recalculation only takes place when explicitly requested, but is not currently exposed in the model editor. OnSaveOrClone has been removed, as has the 'temporary live mode' for newly created entities; for screen reactivity use [CalculationDependency] instead.

  • [ORM] The temporary live mode during save is also gone, but this is actually an improvement - attributes were recalculated repeatedly during save, but it didn't always catch all dependency chains! Now they're recalculated all at once with accurate dependency tracking, and the change-serialising part of the save doesn't have to perform unpredictable lazy loads.

  • [ORM] OnSave (and Manual) properties are now async - you override GetFooAsync instead of GetFoo - and can do efficient data access. Data access should not be done in OnDemand properties, and this will eventually be forbidden.

  • [ORM] Calculation modes are now set in the model editor and the [Calculated] attribute has been removed. The editor can set defaults for individual properties, which will be used if an OnSave or Manual calculation has never run.

  • [ORM] The public flag AttributeBase.ShouldRecalculate is no longer necessary and has been removed; attributes and EntityKernel now have a CalculateAsync() method which immediately recalculates properties regardless of their mode (you can reach the attribute itself through .props). For batch-mode mass recalculations in the datastore, we already have ImportService.RecalculateProperties().

  • [ORM] Cloning objects no longer automatically recalculates attributes of the cloned result; WPF modal screens which used to rely on this feature now call CalculateAsync() explicitly after Clone(). We may be able to get rid of that too, depending on how well the more-precise change notification works.

  • [ORM] The ChangeNotification subsystem used by WPF screens (but also available to anyone who wants a 'notifying context') now requires an 'executor' object; this is used to debounce change events as well as allowing consumers to control the execution context. The whole thing is now O(n) with the total number of deduplicated properties in dependency chains; it used to double-count overlapping chains and suffer exponential blowup when calculated properties depended on other calculated properties.

  • [ORM] EntityReferenceProperty<T> now has Get() and GetAsync() methods, which are shorthand for calling EnsurePresent()/EnsurePresentAsync() before accessing Value.

  • [WPF] Content and Grid screens now guarantee that calculated properties will run on the dispatcher - meaning it's safe to make entity changes from background threads if it happens to affect a calculation dependency. Previously this would lead to errors trying to update fields.

  • [WPF] List screens didn't update cells using calculation dependencies by default, but it could be turned on with Options. Nobody was doing this, though - virtualised lists aren't generally displayed in a situation where dependencies of the list rows can be edited, and it doesn't make much sense as a UI. I've removed the feature; for now it could be restored pretty easily, but I'd like to see if we can do without it.

v221.5.1

  • [WPF] Bugfix: Fix autoupdate not working if the update controller is not served immediately beneath the root.

v221.5.0

  • [WPF] Bugfix: When showing a section as a page in a wizard, it would not be placed in a scroll viewer making tall sections impossible to use without resizing the modal.
  • [WPF] Added ValueField.ShowValueWhenDefaulted which will cause OptionalValue to return a value even if the lens is defaulted.

v221.4.0

  • [WPF] Breaking: IVirtualisedRow.GetCellBackground has been replaced by ConfigureCell which allows applications to override other properties on a DataGridCell.

v221.3.3

  • The.Tool's usage text now includes the push subcommand.
  • [WPF] List screens are once again able to HasChanges if they contain a row which has been edited (this can be done modally if the appropriate options are set);
  • [WPF] Bugfix: Immutable value fields would not appear to update if changes were made to their model.

v221.3.1

  • [WPF] ZomboBox has a new property TextBoxStyle, which can be used to customise the textbox Part of the ControlTemplate within it.
  • [WPF] Refined the inactive-selection-highlight behaviour so that it maintains a visible selection when switching to another application - in which case IsFocused is still true for the control - but not when switching focus within the app.
  • [WPF] Extended inactive-selection-highlight to ZomboBox and PasswordBox when using Inky.

v221.3.0

  • [MODEL] Changing the name of an attribute to the name of its parent entity or another property was not allowed - which is correct - but it didn't even let you type it as an intermediate state, e.g. going from "Fo" to "Foo" on the way to "FooBar". Both WPFEditor and WebEditor now support this.

  • [MODEL] Optimised making changes that affect an entity's name (such as changing the name itself), a lot.

  • [MODEL] Optimised loading large models, an even larger amount.

  • [MODEL] New Attributes now have defaults for ShowInList and ShowInSearch based on how many columns are already shown.

  • [MODEL] Properties used as the DefaultSort ("Sort By") of an entity can now be deleted safely.

  • [ORM] Various ways to save entities now return SaveResult, which contains the set of entities that were saved. This can be used to implement features like automatic reloading or save performance diagnostics.

  • [SQL] Audit Delete records weren't able to capture the deleting user because there is no INSERTED table available to the trigger. SQLEntityStore now works around this by first marking the row as modifiedBy the deleting user, then using DELETED.modifiedBy.

  • [SQL] Audit Update records had their "Text" column set to Create instead of Update.

  • [WPF] Lists can now be sorted by columns of type File or Image without causing errors (though it isn't really useful).

  • [WPF] The following screens now use SaveResult to raise EntitySaved for all affected entities:

    • Create and Display
    • the Delete command in Search screens that allow it
    • List screens opened by the Reminders sidebar
  • [WPF] In the Inky theme, textboxes and zomboboxes with a selection now maintain their visual selection when the application does not have focus.

v221.2.2

  • [REPORTS] We are now using a per-developer licensed version of TX Text Control. Trial popups and watermarks are gone.

v221.2.1

  • [WPF] Bugfix: Showing a section as a page in a wizard could cause that section to be displayed without its data template being registered.

v221.2.0

  • [REPORTS] TX native DLLS are now packaged with The.Reports.Editor, allowing it to run on systems without TX Text Control installed in the GAC.
  • [REPORTS] When the editing pane is in RTF mode, basic formatting commands work on the RTF content (copy/paste, undo, select all, find) and others are disabled.
  • [WPF] ScreenService.WithDisplayContext is now public.

v221.1.0

  • [REPORTS] ReportEditor's sidebar now contains a treeview visualising the report model (if connected to a report server). Model properties can be insert into the template as snippets of code.
  • [REPORTS] Added more word processing features - document/paragraph/character styling, insert objects of various kinds, table management, keyboard shortcuts.
  • [REPORTS] The preview pane now displays structured errors (if there are any errors) and tracks the last-known-good version of the template for reversion.
  • [REPORTS] Either pane can be put in raw-RTF mode with a toggle button in the top left, letting you hand-edit RTF and/or see the results-as-RTF of templating.

v221.0.0

  • [REPORTS] Added new ReportLanguage options: CSharpASPX and CSharpRazor (which is an alias for the original CSharp). This replaces the separate PrecompileASPX method.
  • [REPORTS] Added new package The.Reports.Editor. If you reference it, ReportEditor.exe will be shipped alongside your application and you can use the APIs in The.Reports.Remote to launch a live-previewing template editor.
  • [REPORTS] Fixed a validation error in CSharpRazor reports when using a loop with an empty body.
  • [WPF] deploy.targets now supports creating zips on .NET Core MSBuild, enabling dotnet build for new-style csproj WPF projects using the WindowsDesktop SDK.
  • [WPF] sign.targets now supports using a key stored in a pfx file by setting the SignatureFile and SignatureFilePassword properties.

v220.3.1

  • [WPF] Bugfix: UserRegistrationScreens were missing default grid row field overrides.

v220.3.0

  • [WPF] Displaying and hiding row commands is now faster, which is particularly noticable on complex grids.

v220.2.1

  • [WPF] Bugfix: BuilderExtensions.AddChangePasswordLink was not available for ISubmenuBuilder, only IMenuBuilder.
  • [WPF] AdminUserProfileSearchBehaviour and UseIntegratedPasswordLogin now support deleting user profiles.

v220.2.0

  • [MODEL] The "Extract as reference data" editor command now supports extracting multiple attributes into the new entity, and copies the source attributes' length and precision to the new attributes.
  • [MODEL] Reference relationships can now be "collapsed", deleting the entity on the other side and copying all of its attributes to the current entity.
  • [SQL] Bugfix: Migration SQL with DML statements could fail if run in the same batch as any rename statements.
  • [SQL] Bugfix: The migration SQL generated for CopyAttributes assumed, sometimes incorrectly, that the destination entities would already exist.
  • [SQL] Bugfix: Migration SQL did not always drop triggers soon enough for insert and update statements to work.
  • [SQL] Bugfix: SQL generated for set counts would not delimit the identifier for the set count result.
  • [WPF] Bugfix: Displaying a list with a file column would throw an InvalidCastException.
  • [WPF] FieldModal can now contain a one-line field without stretching it vertically.
  • [WPF] UserProfile display screens no longer have a Create command by default.
  • [WPF] Applications can now create an IntegratedPasswordAuthentication and call The.WPF.Composition.Builder.UseIntegratedPasswordLogin to set up a standard LoginScreen and "change password" and "sign out" menu buttons.

v220.1.0

  • [WPF] List cell background colours can now be overridden.
  • [WPF] The section colour override now uses a linear gradient brush for the header background to more closely match Inky.
  • [WPF] Bugfix: Triggering a notification with a timeout and then closing the tab with that notification before the notification was removed would silently throw an InvalidOperationException.

v220.0.0

  • [WEB] UserRegistrationControllerBase can now be configured to automatically accept registrations.
  • [WPF] Bugfix: MenuBuilder.Default was using different conditions to determine a) how many and b) which entity types are "master data".
  • [WPF] Section colours can now be overridden in applications using SectionExtensions.WithColour or WithBrushes.

v219.1.2

  • [WPF] Bufix: CriteriaModalController would throw NullReferenceException while binding to its Surface and fail to show initial results.

v219.1.1

  • [WPF] Bugfix: Passing a null configuration delegate when creating a Display or Search screen through ScreenService would result in a NullReferenceException.

v219.1.0

  • [IMPORT] Import now converts source nulls into type defaults when importing into non-nullable attributes.
  • [WPF] DisplayBehaviours have been added and can be used to add custom commands to a Display screen.
  • [WPF] Screens can now be prebuilt for feature entities in The.WPF; applications can still override the prebuilt screens.
  • [WPF] There is a new UserRegistration feature for PKI authentication.

v219.0.0

  • [WPF] Bugfix: Generated LookupSectionedCollectionFields would show the Remove command even when not editable.
  • [WPF] Add an override method for the delete command on search screens.
  • [WPF] Controller and field security testability has been improved by using the Principal of their Surface when creating contexts.
  • [WPF] Breaking: Shared lookup contexts have moved to the model of each controller that has one.

v218.3.2

  • [OFFICE] Access import now supports multivalue fields. The multiple values are imported as a separate entity type with a relationship to the parent entity.

v218.3.1

  • [SQL] Bugfix: Fix insert triggers recording a new value that is missing an opening brace.
  • [WPF] Bugfix: BLOB, File, Image and Suggestion fields would not obey immutability.

v218.3.0

  • [SEC] SecurityService now allows a principal to be created for any Identity. The principal is still subject to authentication and authorisation checks.

v218.2.0

  • [WPF] TemplateService has a new method CreateDataTemplate(), which creates but does not register a template.
  • [WPF] Bugfix: Views registered by TemplateService had no NameScope, meaning that {Binding ElementName} and .FindName() didn't work in screen views. Obscure features, but sometimes you need them.
  • [WPF] Bugfix: The licence warning MessageBox was not being shown from the dispatcher, which would throw an exception.
  • [WPF] Bugfix: Data entry fields in a defaulted state wouldn't accept invalid input - which was disastrous if you need the field to be temporarily invalid as you're adding more text to get it valid.

v218.1.0

  • The.Tool can now generate WPF templates with gen -w.
  • [REPORTS] There is a new ASPX-like report format (for C# only) available through ReportManager.PrecompileASPX.
  • [WPF] The.WPF now supports .NET Core. It can be used on either netcoreapp3.1+ or net461+ using the new WindowsDesktop SDK; the hacked-in support for a netfx sdk project remains, but there's no reason to keep using it.

v218.0.0

  • [MODEL] Message boxes in the editor can no longer get stuck behind the active window.
  • [SQL] Bugfix: Renaming an entity or relationship would produce incorrect migrations for triggers.
  • [SQL] Bugfix: Attempting to update a legacy attribute when using legacy mode would silently fail.
  • [TEST] The.Xunit now supports WindowsDesktop test features (for example [STAFact]) when used on netcoreapp3.1+.
  • [WPF] Message boxes opened by TabbedShell and document controls can no longer get stuck behind the active window.
  • [WPF] Bugfix: DisplayController would attempt to preload set counts for entity types that the current principal couldn't read.
  • [WPF] Bugfix: Generated inline reference fields would not use a LazyField if the current principal could not read the target type.

v217.0.0

  • [ORM] Bugfix: A race in EntityReferenceProperty could cause LazyLoad or LazyLoadAsync to fail which usually manifested as an error displayed on list rows.
  • [WPF] The column-resizing Thumbs on datagrids are no longer invisible.
  • [WPF] Bugfix: Generated TextFields were using the wrong constructor, causing them to use the wrong preference key.
  • [WPF] Bugfix: The time part of DateTimePicker was usually not wide enough to display the entire time.

v216.0.6

  • [WPF] Bugfix: Managing the columns of a list would cause an error if the list was sorted by a column with a duplicate caption.
  • [WPF] Bugfix: CreateController's detection of unique index violations while using SQL Server behind The.Web would cause a crash to desktop.

v216.0.2

  • [WPF] Added more logging around PartialEvaluator.EvaluateLocally to help track down THE-1513.
  • [WPF] Bugfix: AccessImportSource was incorrectly trying to override the precision of imported Currency attributes.

v216.0.1

  • [OFFICE] Bugfix: ExcelSpreadsheet would create cells out of order when working with more than 26 columns.
  • [ORM] Bugfix: Document attributes would not raise ValueChanged if their Value property was set.

v216.0.0

  • [OFFICE] ExcelSpreadsheet changes:

    • New CreateNumberFormat method for creating custom Excel number formats like 0.00%
    • New CreateCellFormat overload that takes the NumberFormatId returned from CreateNumberFormat, and supports italics
    • The old CreateCellFormat overload has been deprecated
    • New UpdateCell methods for setting the cell value and style/format at the same time
  • [WPF] Bugfix: Generated decimal and currency range criteria would fail to validate numbers with a decimal point.

  • [WPF] Breaking: The.WPF.Screens.Criteria.Definitions.IsRange has been split into IsIntegralRange and IsDecimalRange. The former has the same behaviour as the original function, and the latter is similar but also matches numbers with decimal points.

v215.2.0

  • [WPF] LookupInlineReferenceField and EntitySelectorModel can now have their choices query filtering function overridden.
  • [WPF] When forcing selection of a ZomboBox, if no particular result is selected, and the search string is not empty, and custom text is not allowed, and the search text has been changed, and there is only a single result available to select based on the filtering function, it will now select that result even if the text of the result does not match the search string.

v215.1.0

  • Fixed a hang in The.Web.Tests.
  • IEntityStore test contracts now run with DisableSyncReads (thereby testing that each entitystore can operate in a mandatory-async environment).
  • [ORM] Added async versions of the query aggregate operators Sum(), Max(), Min() and Average().
  • [ORM] DataContractEntityStore now checks for primary key violations when writing entity changes. This was already an error, but it previously came out as NullReferenceException.
  • [ORM] Bugfix: EntityQueryExtensions.Select<T>(IQueryable<T>, PropertyPath) produced invalid expressions when selecting through collections.
  • [SQLITE] SQLite value queries (.Select(x => x.SomeAttribute)) only had limited support. They now work for most attribute types, with the notable exception of Currency.

v215.0.0

  • Added a new package, The.Web.Components, containing prototype scaffoldable entity UI. These components can be used either in an ASP.NET Core 3.0 app or a Blazor WebAssembly client-side app - though there isn't really enough there to be useful yet. Eventually, The.Web will depend on The.Web.Components, but not until it requires .NET Core 3.
  • [ORM] Bugfix: Concurrently reifying an entity would sometimes throw a ContextMergeFailureException.
  • [ORM] Bugfix: Deep cloning could cause change events to be raised before the clone was complete.
  • [SQL] Fixed migration generation when an entity with existing relationships was made transient/persistent - this now creates or deletes join tables as necessary.
  • [WEB] Removed AddTheSPA() and the React-based AdminSite prototype. From now on The.Web will contain only server-side functionality.
  • [WPF] Bugfix: Collection cells in virtualised lists would sometimes display the value from a different row if the user had scrolled the list.
  • [WPF] Bugfix: Preferences were disposed before sidebars, which prevented them from storing any preference changes during unloading. This fixes RecentItemsController never persisting recent items.

v214.3.0

  • [WEB] Endpoint.ConnectAsync will now log when returning an error to the client.
  • [WPF] Bugfix: String "has value" criteria would incorrectly identify a " character as no value, and would fail to recognise empty string as no value.

v214.2.0

  • [ORM] Cloning an entity with File/Image attributes didn't work properly. The underlying ID of the document was preserved, so a save would work, but the presentational FileDocument or ImageDocument was not copied across. This meant the public api (.Value, HasChanges(), etc) would behave as if no document was set.
  • [WPF] LVSCF.Remove and GVSCF.Remove are now overridable by subclasses. They also have a new override point CreateSubcontroller. This is useful when you're using custom controller types and need something out of their concrete interface - it might be replaced with dependency injection or display contexts in future.
  • [WPF] Non-async subtitles are supported again, but don't use it for sync-over-async!
  • [WPF] Bugfix: VIRF's create button would use a DisplayModalController rather than a CreateModalController.

v214.1.0

  • [SQL] Bugfix: SQL Server migration would generate SQL statements in an incorrect order if an attribute was renamed and had its type or nullability changed in the same event.
  • [WEB] Endpoint will now check if the identity performing an operation is actually authorised.

v214.0.0

  • [ORM] Breaking: .Copy() and .Clone() are now extension methods rather than generated code, so they're available on all IEntitys and can be used in generic methods.
  • [WPF] Configuration can now be applied to all screens of each kind by modifying the The.WPF.Composition.Options' ScreenConfiguration property. This configuration will be applied before other overrides.
  • [WPF] ValueInlineReferenceField is no longer prone to ContextMergeFailureExceptions when used to Create a complex entity - it operates in a clone of the parent's context, which can then be cloned back.
  • [WPF] Bugfix: DisplayController's detection of unique index violations while using SQL Server behind The.Web would cause a crash to desktop.
  • [WPF] Bugfix: Selecting new displayed columns for a Grid would cause the left-most field to be duplicated.

v213.1.0

  • [ORM] All IHasChanges implementations (values, sets, entity kernels) now have a consistent implementation of NeedsSave(), which was previously available on an ad-hoc basis. Change description uses it consistently, too - no more seeing changes to calculated properties on the "really close tab?" modal just because you entered real data.
  • [SQLITE] Nullable types basically didn't work at all.
  • [WPF] Row numbers and row command buttons on List screens were appearing at the wrong X position, screen-relative instead of widget-relative, on certain computers. A speculative fix has been implemented which may alter this.

v213.0.0

  • [ORM] Breaking: Legacy relationships no longer have the "legacy" prefix.
  • [ORM] The.Core is now largely compatible with WebAssembly. Certain features aren't supported - notably sync reads, and therefore lazy loads in non-async contexts.
  • [ORM] Creating contexts is slightly more efficient.
  • [ORM] Bugfix: It was not possible to load an entity in legacy mode if it had any legacy relationships.
  • [SQL] Bugfix: SQL based entity stores would fail to insert entities that had legacy attributes.
  • [WEB] Breaking: The.Web no longer supports .NET Framework - only .NET Core.
  • [WEB] The.Web now has preliminary support for ASP.NET Core 3; it still works with 2.1 or 2.2 for now.
  • [WPF] DisplayController's On___ hooks now have async variants.
  • [WPF] Bugfix: RecentItemsController would throw an exception during sidebar registration if one of a user's saved pins referred to an entity type that no longer exists. This could be triggered by renaming an entity type, or marking one as legacy.

v212.3.2

  • [ORM] DataContractPersistence.cs now contains an // <auto-generated /> comment that indicates to Roslyn not to analyse it.
  • [ORM] CurrencyProperty and NullableCurrencyProperty now override ToString to format the result as currency. This affects the output of reports.
  • [WPF] Grid screens no longer have the same 'Row #' display as List screens - these are intended to contain small amounts of data.

v212.3.1

  • [ORM] Fixed a bug in the new save algorithm.

v212.3.0

  • [ORM] Improved save performance - most save graphs would be evaluated at least twice in order to check whether the first evaluation produced any changes (due to calculated properties and lifecycle hooks loading extra data). SavePlanner now uses a better algorithm which can detect this with only one pass.
  • [ORM] OpGenerator - the thing you get from AsReadOperation() - now supports Sum().

v212.2.1

  • [SQL] Bugfix: Null-coalesced value queries on other than integral types were sometimes producing an InvalidCastException when reified.

v212.2.0

  • [SQL] SQL Server migration now supports CopyAttributes, CopyForeignKey, and CopyRelationship events, which means that the "Convert to relationship", "Use as foreign key...", and "Extract as reference data" editor commands can now be used when data has already been imported.
  • [SQL] Framework Decimal values are now stored in SQLite as floating point strings - this works surprisingly well, enabling in-DB decimal arithmetic. It's also higher performance, as it aligns with how Microsoft.Data.Sqlite (the underlying ado.net provider) treats them.

v212.1.6

  • [SQL] Fixed some query translation edge cases - Average() and Max() of zero-row resultsets now behave "correctly", meaning that they produce 0, null or exceptions in the same circumstances where Linq 2 Objects would do so. In particular, emptyQuery.Sum() is no longer an error, and emptyQuery.Average() now is an error.

v212.1.5

  • [ORM] Calculated properties are now cached during each 'pass' of a save, so that calculating simple derived properties which rely on expensive base properties doesn't incur the cost again.

v212.1.3

  • [ORM] Bugfix: EntityBase.OnSaved and EntityContext.Saved could be called/invoked twice when a graph containing autonums was saved.

v212.1.2

  • [ORM] Bugfix: EntityContext.Get<T>() flat-out didn't work. Non-generic Get() works, which is probably why nobody noticed.

v212.1.1

  • [ORM] EntityContext now raises an async event called Saved after a save completes, with the IEntityInfos that were saved as a parameter. This can be used to update UI containing those types or just to take actions based on a save having occurred. The SaveAsync() call which triggered the Saved event will not return to the caller until the event handler is complete, but its work is done, so it's ok to perform more saves in the handler if it can deal with reentrancy.

v212.0.0

  • [ORM] Hybrid queries now use a three-state system - loaded, unloaded, requires-load-to-enumerate-or-query.

  • [ORM] The binary loadedness RelationshipProperty.IsPresent is no longer used by ORM operations. "Presence" is not required anymore for saving, change-checking, etc - partially loaded entity graphs can be correctly serialised without any lazy loads.

  • [ORM] IEntitySet<T>, the interface to collection properties, is no longer a subtype of ICollection<T>. ICollection is inappropriate for what are basically mutable queries which generally don't become fully loaded into memory. Specific changes include:

    • removed CopyTo(T[])
    • added RemoveRange(), the counterpart of AddRange()
    • added AsUnloaded(), the counterpart of AsLoaded() - this is an assertion which will only give you a query if it would run on the server, and throws otherwise
    • Add/Remove[Range] calls no longer require lazy loads for 1:n relationships (many-to-many requires a load in order to see whether the relation already exists).
  • [ORM] Both direct and "remote" changes to collection properties now trigger the new requires-load state, addressing a class of application bugs where business logic code would make in-memory changes and then execute a search which inadvertently failed to account for those changes.

  • [ORM] OnSaved[Async] is now called for entities which had one of their relationships altered.

v211.0.1

  • [ORM] Bugfix: The OnSaved/OnSavedAsync lifecycle hook wasn't firing when an entity was deleted, unless other changes were made during the same save.

v211.0.0

  • [WPF] Breaking: Section subtitle generators are now async and are generated sequentially on the dispatcher at a low priority.
  • [WPF] Bugfix: CollectionSection would not update its subtitle if its underlying collection changed unless wrapped in a SubtitledSection.

v210.2.1

  • [SQLITE] SQLiteMigrationGenerator produced bad DDL in an edge case - if you created a relationship between entities A<->B which was the only relationship on entity A, gave one of its sides a name override, then later added another A<->B relationship, the join table for the existing table would not be updated to get a disambiguated name.

v210.2.0

  • [LINQ] Fixed false positive in analyzers - static method calls are no longer checked as if the declaring type's identifier was the identifier of closure variable.
  • [LINQ] Math.Min() and Math.Max() are now supported in queries.
  • [SQLITE] Bugfix: SQLiteEntityStore wasn't able to correctly save relationships to tables which had an autonum column.

v210.1.3

  • [ORM] DataContractEntityStore is now better at detecting [what would in SQL be] UNIQUE KEY violations.
  • [ORM] Bugfix: The change to remote updates in 210.1.2 is now more comprehensive. Previously the references ended up loaded-enough to clone, but not loaded-enough to save if saving required issuing a DeleteRelationship op to maintain a unique key invariant.
  • [WPF] Virtualised lists can't really tell when a cell changes, and not all entity properties modifiable by opening list rows have columns. Accordingly, ListValueSectionedCollectionField will now raise HasChanges/IsValid change events when its managed list goes through a modal.

v210.1.2

  • [ORM] Bugfix: Remotely setting a 1:1 reference relationship which was unloaded didn't cause it to become loaded - this led to subtle and then increasingly overt problems down the line if the bad graph was repeatedly cloned, saved or otherwise manipulated without the pseudo-unloaded reference ever being inspected (which would fix up the graph).

v210.1.1

  • [ORM] The return value of the .AsReadOperation() query operator can now be used as a read operation directly - this is equivalent to calling .AsReadOperation().AsEnumerable(). This is basically a convenience for query-batching; it lets you write code like

    var results = await Services.Persistence.ReadAsync(ctx, 
      q.Where(h `=>` h.Name == "search1").AsReadOperation(), 
      q.Where(h `=>` h.Name == "search2").AsReadOperation()
    );
    
  • [SQL] Fixed a class of bugs around parameter name clashes - parameter ids are now assigned cooperatively by the various things that assign them. One example of a problem caused by this structural flaw was demonstrated by RemindersController; it batches together multiple QueryEntities operations, so if you had more than one IReminder with a Where() clause containing a string-literal (parameterised for security) then loading the reminder counts would fail.

v210.1.0

  • [EXPORT] When exporting a query, IColumn paths referring to relationships will now be loaded during the export rather than showing up as <not loaded> in the output.
  • [SEC] Client-server encryption sessions can now be successfully re-established if the client believes it has a session but the server does not (for example, because the service has restarted). This involves re-issuing the failed read op, and does not result in an error on the client side.
  • [SEC] The WebEndpoint(string) constructor now supports specifying a port number (as in "http://localhost:12345/").
  • [SEC] PasswordAuthentication has a new static method to create correctly-realmed identities.

v210.0.2

  • [ORM] Added a new diagnostic to The.Core.Analyzers. THE003 checks for attempts to close over complex data - you can't, for example, compare an entity in the database to an entire entity in memory (as the serialisation system does not support sending the in-memory entity down to the server). This was a source of runtime errors.

v210.0.1

  • [WPF] AutoUpdater.DownloadOrInstall now includes an option to forcibly kill the updating process. This is to workaround an issue with a specific client's SOE which prevents the application from ever closing, except if forcibly killed.
  • [WPF] Bugfix: ReferenceDataController would not show a scrollbar if there were too many items to display at once.

v210.0.0

  • [ORM] Added analyzers to The.Core, providing diagnostics and codefixes for some ORM usage patterns that are outside the scope of C#'s ordinary type system. Initial analyzer features:

    * Detect LINQ query operators which are unsupported in datastore queries
    * Detect LINQ query predicate/projection expressions containing functions unsupported in datastore queries
    * Rewrite LINQ queries to execute in memory when not supported by the datastore
    
  • [ORM] Coming full circle, IOwnedSet is now IEntitySet once again (as there's no other kind of entityset anymore). It has a new method, AsLoaded(); this will give you a non-copying enumerable if the set/probably-collection is already loaded, or throw otherwise.

  • [SQL] Added query translation support for string.IsNullOrEmpty() and string.IsNullOrWhitespace().

  • [SQL] Bugfix: query.Take(0).FirstOrDefault() was incorrectly returning non-null, effectively applying Take(1) instead of Take(0).

  • [WPF] WPF composition and IShell have been revamped to support more granular init. Shells are now given notice of exactly when the global WPF environment is 'ready'; this is the point at which a splash screen or the main window can be displayed, giving the user progress bars etc.

    In particular, the shell can display after data templates and WPF resources have been loaded but before remote login or license-checking is done. LoginScreen does not use this mechanism yet but it may in future.

  • [WPF] Bugfix: ReferenceData screen failed to display summaries for entities with a default sort order.

v209.1.1

  • [WPF] LoginWindow now includes the app version.
  • [WPF] ZomboBox was failing to close its dropdown in some cases.

v209.1.0

  • [ORM] Reminders can now be created from context->query functions. These constructors, from specs and expressions, were already present:

    IReminder reminder = new `Reminder<Human>(new` HumanSpecification(), "");
    IReminder reminder = new `Reminder<Human>(h`` =>` h.Owns != null, "");
    

    This one is new: IReminder reminder = new Reminder<Human>(Human.Query, ""); // uses method group conversion IReminder reminder = new Reminder<Human>(c`` => Human.Query(c).Where(h => h.Owns != null), "");

  • [WPF] Logging at sub-TRACE levels no longer includes screen titles. These may contain sensitive application data.

  • [WPF] The search button (magnifying glass icon) on EntitySelector views is now hidden until the zombobox is first searched/dropped down. Lookup Inline Reference Fields which go into editable mode (the "..." button) will also activate this.

v209.0.2

  • [WPF] LoginScreen itself is now themeable to match the application.

v209.0.1

  • [WPF] Bugfix: theming was broken if you used LoginScreen.

v209.0.0

  • [ORM] Added optional async Get/Verify methods to IAuthentication.

  • [ORM] Made IRemoteAuthentication.EncryptData async (mandatory - all implementations are slow in one way or another).

  • [ORM] Added SecurityService.CreatePrincipalAsync(). This is more efficient than CreatePrincipal(), which blocks both on IAuthentication and on Connect() when authenticating over HTTP.

  • [ORM] Added support for EmptyQuery to entity stores. You can now write query operators like this:

    .SelectMany(f `=>` f == null ? `EmptyQuery.Create<Dog>()` : f.Dogs)
    
  • [WEB] WebAuthentication no longer attempts to cache an authenticated identity after an HttpContext ends - this just isn't possible to do reliably. We will need to ensure that IAuthentication.GetIdentity isn't called unnecessarily when you save a context or a principal for later reuse.

  • [WPF] Clicking in the blank space within a checkbox field will now focus the checkbox without activating it.

  • [WPF] SessionService.Login is now LoginAsync. This handles network I/O correctly (without threading) as well as slow authentication mechanisms like PKI tokens.

  • [WPF] LoginScreen will now display the login/splash screen immediately upon construction, before the framework starts up its shell or autoupdates. It displays a progress bar when some operation has disabled interactivity.

  • [WPF] LoginScreen can optionally be given an HttpClient representing the autoupdate server, allowing the splash screen to handle autoupdate rather than the shell.

v208.1.5

  • [WPF] Bugfix: The autoupdater would sometimes show an exception that a "Process with an Id of {PID} is not running." if the old process exited too quickly.

v208.1.4

  • [WPF] Time fields are back to using a textbox, but they still have the TimePicker-like feature of canonicalising times on focus loss.

v208.1.3

  • [WPF] OnLogout handlers now run before the shell does anything (e.g. reacting to logout of its own accord).

v208.1.1

  • [WPF] Small changes to the LoginWindow design.

v208.1.0

  • [WEB] WebAuthentication (the default IAuthentication when using The.Web) now captures the authenticated identity it retrieved from the HttpContext; this works around ASP.NET Core 3.0's more aggressive clearing of the HttpContext, so that long-awaited tasks can continue after their associated HTTP request is over.
  • [WEB] The.Web is built against ASP.NET Core 2.0, but works to some extent with 3.0. One thing which didn't previously function was generating templates - the extension would fail to generate if a 3.0 project referenced The.Web. This now works.
  • [WPF] Generated screens now use ValueInlineReferenceField instead of ValueSectionedReferenceField. FieldFactory.CreateValueReference has been removed; use the constructor of the desired field type instead.
  • [WPF] ValueInlineReferenceField's Clear command now deletes the child entity as well as unlinking it from the parent, just like ValueSectionedReferenceField's Delete command does.
  • [WPF] A standard login screen has been added in The.WPF.Shell.Login. It provides hooks for PasswordAuthentication, WPF.Composition.OnLogout and TabbedShell(SplashScreen).

v208.0.0

  • [IMPORT] Pipeline has a new SetCustomConversion overload which applies the conversion to all columns with the given source and destination types.

  • [MODEL] ModelSnapshot has a new ToEvents method which creates a new history with an identical snapshot.

  • [MODEL] Extension: The extension now supports Visual Studio 2019.

  • [MODEL] Extension: The extension now loads in the background using AsyncPackage (so Visual Studio might start up a bit faster).

  • [MODEL] Bugfix: SerialisableEventCollection's ReadXml method was eating a little too much of the input XML. This was not an issue when <History> was the last element in the file, but becomes problematic when more elements are added after it.

  • [MODEL] WellKnownFeatures is now part of The.Model; editor classes that maintained their own list of features now use WellKnownFeatures instead.

  • [MODEL] Model features now have versions and automatically upgrade when a model file is loaded.

  • [MODEL] The "User accounts" feature has a few changes:

    • UserProfile.DisplayName has a maximum length of 80
    • UserProfile.LastLogon is nullable
    • UserClaim.Key has a maximum length of 255
    • UserClaim.Value is a Text attribute
  • [ORM] Bugfix: Export would leave junk at the end of the output file if overwriting an existing file that was longer than the new content.

  • [SEC] Authorisation bugfixes.

  • [WPF] Bugfix: Excel export sometimes failed to calculate some properties.

  • [WPF] Bugfix: An unclear error message was displayed when attempting to open a Display screen for a nonexistent entity.

  • [WPF] Customisations to DatePicker text have been removed - our new guidance is to set the "Switch.System.Globalization.NoAsyncCurrentCulture" AppContext switch to True for WPF applications.

  • [WPF] Inherit from the new The.WPF.FrameworkApplication class instead of from System.Windows.Application to have the AppContext switch set automatically, as well as including the Inky theme by default.

  • [WPF] Time fields now use the TimePicker control instead of a standard TextBox.

  • [WPF] Bugfix: EntitySelector's behaviour of not filtering suggestions when there are no matches combined poorly with ZomboBox's behaviour of selecting the first suggestion on tab-out when there are no matches.

  • [WPF] ZomboBox now handles Enter keypresses similarly to how it handles losing keyboard focus.

  • [WPF] ZomboBox has a new KeyboardFocusLossBehaviour property which can be set to RevertSelection to disable its behaviour of selecting an item when tabbing or clicking out.

  • [WPF] Added combinator ISection.WithoutField, which lets you remove one IField from a section in overrides. If it doesn't have that field in it, WithoutField does nothing.

  • [WPF] Added ScreenService.GetDisplayContext(), which will tell you whether an ISurface is being used to display some IProperty (and which one).

  • [WPF] Relationship fields now set a displaycontext, allowing their inner List and Content screens to hide columns and fields for the property that refers back to the parent.

  • [WPF] Shell components that used SystemColors.MenuBarBrushKey and MenuTextBrushKey now use the new The.WPF.Shell.Resources.ThemedBarBrushKey and ThemedTextBrushKey instead. Themes should override these keys instead of the SystemColors keys to avoid unwanted side-effects in standard Windows menu styles.

  • [WPF] AutoUpdater improvements:

    • The current process ID will be logged when shutting down.
    • The installation path passed to the ApplicationData process is now surrounded by double quotes.
    • The current process ID will be passed to the update, which will wait for only that process to finish (and not other processes with the same name).
  • [WPF] Implementations of SectionedCollectionFieldBase can and must now specify the type of their subscreen model (ListModel for the existing implementations).

  • [WPF] List screens can no longer be "inline"; this concept has been split out into the new Grid screen type.

  • [WPF] Grid screens are for editing multiple (but not large numbers of) entities at once - they always contain fields (like an old IsInline List screen) and do not virtualise their rows. GridRowBase takes over from ListRowBase in terms of being overridable and having overrides generated.

  • [WPF] List screens are for displaying large numbers of entities at once without the ability to edit them - they display only read-only data (no fields) and virtualise their rows. ListRowBase has been replaced with ListRow, which no longer requires overriding in most cases.

  • [WPF] ValueSectionedCollectionField has been split into ListValueSectionedCollectionField and GridValueSectionedCollectionField, whose subscreens are List and Grid respectively. FieldFactory.CreateValueCollection (and generated content screens, which use it) will use the old default IsInline calculation to determine which of these fields to create.

v207.2.2

  • [IMPORT] Added some logging to RecalculateProperties, including timing information and detection of unmarked calculation dependencies.

v207.2.1

  • [WPF] Fixed bug in Models.tt template which generated incorrect viewmodels.

v207.2.0

  • [ORM] Added an optional IPrincipal parameter to ImportService.CalculatePropertiesAsync. If none is provided, it will use the ambient principal as it currently does.
  • [WPF] LookupSectionedCollectionField's selector for adding is no longer always visible. The Add button now displays the selector and transmutes into a Cancel button. Selecting an item in the selector adds it to the collection and hides the selector.
  • [WPF] Bugfix: DatePicker has had a stern talking to and will now respect other cultures.
  • [WPF] If RemindersController is removed or reset, it will reload the list of reminders.
  • [WPF] The floating panel that appears on list rows and contains the row number and row command buttons now has a white background.
  • [WPF] Multiple VirtualisedLists attempting to preload data into the same context will now take turns.

v207.1.1

  • [SQL] Fixed ChangeAttribute migration to avoid generating changes to transient columns.

v207.1.0

  • Added new package The.SQLite, containing SQLiteEntityStore and various support types like SQLiteDatabase. This is a reasonably full-fidelity store, with all the same features as SQLEntityStore except for generation of audit logs using triggers. It can be used in-memory using special SQLite connection strings, using a local file, or using a file on a network share. The.SQLite contains a new template to generate migrations in .theSchema format or as a .sql file; it doesn't require a generated PersistenceMetadataDictionary.
  • [ORM] Removed support for inheritance in IEntityInfo.
  • [ORM] IEntityContext now inherits from IEquatable<IEntityContext>.
  • [SQL] QIR now supports UPDATE statements.
  • [SQL] QIR INSERT statements now support using a value-list instead of a source query.
  • [SQL] (SQL|Access)MigrationRunner now use the same PersistenceMetadataDictionary as (SQL|Access)EntityStore to generate queries that can use each db's unique capabilities.
  • [SQL] QIR no longer supports string constants at all - this is in order to comprehensively prevent SQL injection vulnerabilities. Anywhere that a literal would previously have been produced, query translation produces parameterised queries.
  • [WPF] Collection fields that had a button to remove the selected row now instead add a remove command to each row. This can be suppressed (to hide the remove command or to replace it with a different one) by setting the suppressRemoveCommand constructor parameter to true.
  • [WPF] Display screens' save notification now contains a timestamp.
  • [WPF] Fixed bug in RelationshipOptionsField - it uses what used to be an IEntitySet but is now an IQueryable, and was inadvertently trying to pass a lambda through the IEndpoint to execute in SQL. Now it uses an async valuequery for .Text.

v207.0.0

  • [MODEL] The editor no longer allows you to make Boolean attributes Required.

  • [ORM] Removed support for inheritance in DataContractEntityStore.

  • [ORM] ImportService.CalculateProperties now reports progress accurately instead of underestimating time and then running in the background.

  • [ORM] ImportService.CalculateProperties now understands [CalculationDependency] attributes and will perform deep preloading - an O(m^n) improvement.

  • [ORM] .Select(RelationshipInfo) now does null-checking for reference chains, similarly to .Select(PropertyPath).

  • [SQL] Removed support for inheritance in both schema and DML.

  • [SQL] QIR now models Insert and Delete statements as well as Select. Some persistence functionality which used to be implemented per-backend is now common, with opportunities to share more code in the future.

  • [SQL] Query translation now supports the projected forms of aggrgeate functions like Sum and Max - this kind of query:

    Human.Query(ctx).Sum(h `=>` h.Age)
    
  • [SQL] Query translation optimises away some null-checks which are unnecessary under SQL nullability semantics. All three of these operations are now equivalent:

    .Select(h `=>` h != null ? h.Owns : null)
    .Select(h `=>` h == null ? null : h.Owns)
    .Select(h `=>` h.Owns)
    

v206.2.0

  • [SQL] Query translation supports arbitrarily nested subqueries. In a case like Foo.Query().Where(f => f.Bars.Any(b => ???)), the subquery ??? can be as complex as the outer query itself, with subsubqueries etc.

  • [SQL] Query translation supports arbitrarily chaining selections using nested queries (which are emitted as common table expressions if possible. Some examples of what's now possible:

    var initialQ = Human.Query(ctx).Select(h `=>` h.Name).Distinct().Select(h `=>` h.Substring(0, 1)).Distinct(); // re-distinct
    Assert.Equal(3, initialQ.Count()); // M, D, Y
    var uniquesQ = Cat.Query(ctx).Select(c `=>` c.Farm).Distinct().SelectMany(f `=>` f.Cats); // select collection from distinct query
    Assert.Equal(3, uniquesQ.Count());
    var skipQ = Farm.Query(ctx).OrderByDescending(f `=>` f.Cats.Count()).Skip(1).SelectMany(f `=>` f.Cats); // select collection from paged query; order by aggregate subquery
    Assert.Equal(1, skipQ.Count());
    Previously these patterns would lead to errors like "SelectMany() is not supported following a Distinct()".
    
  • [SQL] Bugfix: The DeleteQueryTables SQL agent job now escapes the database name.

  • [WPF] Bugfix: ValueInlineCollectionField and ValueSectionedCollectionField continued to accept ListOptions parameters but ignored them. They now have optional Action<ListOptions> parameters instead.

v206.1.0

  • [WPF] Refinements to the new screen options configuration system:

    * `"Action<Options>` configure" parameters of ScreenService methods are now optional 
    * `"Action<Options>` configure" parameters of screen constructors are now optional 
    * Screens have a new overridable method ConfigureOptions, which can be overridden by subclasses to apply customisations before, after or instead of the caller-supplied configuration delegate.
    * ScreenControllerBase now implements this in a uniform way for all subclassable screens.
    

v206.0.0

  • [IMPORT] Import sources are now required to provide length and precision information for all imported attributes.

  • [MODEL] Split the editor into a 'headless' controller-model layer, provided by The.Model, and a WPF frontend in The.Model.WPFEditor.

  • [MODEL] Added a new WebAssembly-based frontend in the new package The.Model.WebEditor.

  • [MODEL] Deleting old versions or deleting the intermediates when naming a version is now faster, and no longer hangs the UI.

  • [MODEL] Searching by typing into the treeview now shows you children of search-matched nodes, as well as the matched nodes themselves

  • [MODEL] Filled in editor documentation for some more flags and elements.

  • [MODEL] Creating attributes now sets some useful defaults based on the type.

  • [MODEL] WPFEditor: Text in the editor error window is now selectable.

  • [MODEL] WPFEditor: The right-hand editor panel can now be scrolled when its content is too large for the viewing area.

  • [MODEL] WPFEditor: The search feature now searches within labels, captions, and plurals, not just within names.

  • [MODEL] WPFEditor: Errors raised while searching will now be displayed in a message box, hopefully preventing this cause of Visual Studio crash.

  • [OFFICE] Added two new IDatabase implementations, AccessDatabase and TempDatabase. These types use OLEDB to create or open an existing .accdb/.mdb file.

  • [OFFICE] Added a new AccessEntityStore, which uses an .accdb file as a backend.

  • [OFFICE] Added templates to generate AccessPersistence and an AccessMigrations.theSchema - no .sql file, as Access can't run multiple statements from a file. This .theSchema should be executed with AccessMigrationRunner.

  • [ORM] The "persisters" dictionary is now a specific type - PersistenceMetadataDictionary - which has a new IsLegacy flag. PersistenceService will check that the EntityMetadataDictionary's IncludesLegacyAttributes flag matches the new flag when connecting, and raise a NotSupportedException if not. This helps to prevent applications incorrectly composing the framework to use legacy entity metadata but non-legacy persistence metadata or vice versa.

  • [ORM] Bugfix: the Specifications template generated a "Make field readonly" [sic] suggestion for each entity type in the model.

  • [ORM] Bugfix: AppDataPreferenceStore would never create the preferences file.

  • [ORM] Bugfix: DataContractEntityStore did not apply case-insensitive collation when backed by an XML file.

  • [ORM] IEntityStore's methods now take an Identity parameter instead of IPrincipal. No store used the principal except to get its identity, and SecureStore already ensured that the principal was authenticated before calling IEntityStore methods.

  • [ORM] IPrincipal's Identity property has been replaced with AuthenticatedIdentity, which is null unless the principal is authenticated. The new ErrorDescription property contains the error description that was previously in Identity for unauthenticated principals.

  • [ORM] PropertyPath has two new members:

    • Length returns the number of properties in the path
    • GetPrefixes() returns all prefixes of the path, including the empty path and the path itself
  • [ORM] IQueryable<TEntity>.Select (from EntityQueryExtensions) now has an overload that takes a PropertyPath.

  • [ORM] Bugfix: DataContractEntityStore did not handle null constants of entity types in queries.

  • [ORM] Bugfix: DataContractEntityStore threw a NullReferenceException when Selecting through a relationship with at least one null value.

  • [REPORTS] Comments (e.g. "@* comment goes here *@" without the quotes) are now supported in C# templates.

  • [SQL] SQLEntityStore now requires SQLDatabase rather than any IDatabase; LocalDatabase is a subclass of SQLDatabase for using LocalDB.

  • [SQL] Schema manipulation types like MigrationGenerator and MigrationRunner are now SQLMigrationGenerator, SQLMigrationRunner, etc.

  • [SQL] Fixed sql generation bug when batching together a very large number of write operations.

  • [SQL] Bugfix: If given enough queries to require multiple batches, SQLWriter would run the last batch multiple times using the parameters of each batch in turn, instead of each batch once using its own parameters.

  • [SQL] Bugfix: The test "StartEnforcingNonNullability_CommonProps" was flaky. Now it might not be..?

  • [UTILITY] IEnumerable extension methods Append() and Prepend() have been added to .NET Core 2.0+. Moved our versions of them up from The.Model to The.WPF (which does not use .NET Standard or Core yet).

  • [WPF] The 'Tasks' sidebar is now the 'Reminders' sidebar.

  • [WPF] List screens can now have behaviours added through ListOptions; behaviours can currently only add custom row commands.

  • [WPF] SearchController now optionally adds a custom row command to delete an entity; enable it with SearchOptions.CanDelete (which defaults to false).

  • [WPF] The reference data screen has been rewritten:

    • Entities are now displayed as hyperlinks.
    • Selecting an entity used to convert the screen into a heavily customised search screen, but now opens a normal search screen with CanDelete enabled instead.
    • Instead of attributes and relationships, the count and first 20 Text values for each entity type are listed.
  • [WPF] Screen configuration now works similarly to ASP.NET Core options.

  • [WPF] Bugfix: up to one collection field in the Main section could be hidden incorrectly.

  • [WPF] Bugfix: The test "List.MultipleRefresh" was flaky. Now I am pretty sure it is not.

  • [WPF] FieldBase<T>.SetViewFromModelAndNotify is no longer abstract and now requires the Dispatcher. Existing custom fields that overrode SetViewFromModelAndNotify should now override SetViewFromModelAndNotifyInternal, and no longer need to check/take Dispatcher access themselves.

  • [WPF] List rows now display the row number of the moused-over row at the far right, just to the left of any custom row command buttons. This can be suppressed by setting the new ShowRowNumberText list option to false.

  • [WPF] List screens have a new CanOpen option; setting this to false makes the first column a text column instead of a hyperlink column, disables the ability to open items by double-clicking, and removes the "Open In New Tab" row command. The default value is true.

  • [WPF] RelationshipSearchField's criteria popup has been separated into a new CriteriaModal screen and now previews the entities matching the entered criteria.

  • [WPF] ISurface has two new properties:

    • ContentContainer returns the UIElement displaying the screen content
    • CurrentModalContent returns the currently-displayed screen model if there is one, or null otherwise Rough instructions for a basic app:
    • Inherit from one of these classes for each custom screen that will be documented: o DisplayScreenDocumentor o DisplayModalScreenDocumentor o SearchScreenDocumentor o ScreenDocumentorBase o ModalScreenDocumentorBase
    • In your menu initialisation function, wrap the given IMenuBuilder in a DocumentingMenuBuilder
    • Call DocumentingMenuBuilder's methods, passing screen documentors instead of controller providers
    • Generate the model for a manual by calling ManualGenerator.GenerateManualAsync
    • Template the model into a document by whatever means available
  • [WPF] The new DispatcherExtensions.WaitAsync extension method can be used to wait until dispatcher activity quiets down; this is useful for screenshot generation.

v205.1.3

  • Added support for cross-platform builds to The.Tool. ./test.sh <prerelease-version> does the same thing on macos or linux that test.bat <prerelease-version> does on windows. By taking better advantage of the .NET Core CLI, test builds are now far faster:

    prospit:framework banana$ time ./test.sh 206.0.0-a Successfully created package '/Users/banana/Documents/Agile/framework/artifacts/The.Xunit.205.1.3-a.nupkg'. Successfully created package '/Users/banana/Documents/Agile/framework/artifacts/The.Model.205.1.3-a.nupkg'. Successfully created package '/Users/banana/Documents/Agile/framework/artifacts/The.SQLServer.205.1.3-a.nupkg'. Successfully created package '/Users/banana/Documents/Agile/framework/artifacts/The.Web.205.1.3-a.nupkg'. Successfully created package '/Users/banana/Documents/Agile/framework/artifacts/The.Core.205.1.3-a.nupkg'. Successfully created package '/Users/banana/Documents/Agile/framework/artifacts/The.Reports.205.1.3-a.nupkg'. real 0m12.852s user 0m9.386s sys 0m2.308s

  • [WEB] Fixed AddUserProfileStores() registering scoped deps which end up captured by Identity in a singleton, poisoning future injections of IEntityContext with an anonymous Identity.

v205.1.2

  • [SQL] Ported migration fixes from 204.4.8 and 204.4.9.

v205.1.1

  • [WPF] Faster shell startup.

v205.1.0

  • [ORM] DCES: fixed query translation bug affecting ComponentService.GetCurrentUserProfile().
  • [ORM] Options.DisableSyncReads is now actually implemented.
  • [ORM] Fixed DynamicBivariantSet.CopyTo failing when TOut is an interface type - this requires using an intermediate array rather than relying on unsound array covariance.
  • [ORM] Introduced a limited form of two-phase initialisation for component entities - component interfaces may implement ITwoPhaseInit, which lets the framework test whether an entity has been given a kernel yet and supply one if not. Normal entities do not have this 'feature'; it exists only to support some integrations which require parameterless entity construction.
  • [SQL] QIR emit now supports empty sequences ('WHERE ID IN (NULL)').
  • [SQL] QIR translation now implements simple constant-folding and boolean-algebra optimisations so that we don't end up running useless queries like 'WHERE ID IN (NULL)'.
  • [SQL] SQL entity store and document store no longer use ConfigureAwait(false) internally; now that our UI uses async reads and writes, the better tradeoff is to remove the deadlock prevention mechanism in favour of marshalling work back to the dispatcher to prevent data races.
  • [WEB] WebAuthentication has better error handling.
  • [WEB] Added integration with ASP.NET Identity - IUserProfile component entities like My.App.UserProfile are now Identity-compatible user types. The new .AddUserProfileStores() extension method on IdentityBuilder works like .AddEntityFrameworkStores() from the ASP.NET docs. When used with username/password signin, profile-based users are compatible with the identities and hashes managed by The.Security.PasswordAuthentication.
  • [WPF] RelationshipOptionsField - the criterion which has a magnifying glass that brings up a grid of checkboxes - no longer generates needless searches for sets of 0 options.

v205.0.1

  • [SQL] Added LINQ support for the null-coalescing operator "??".
  • [SQL] Fixed MigrationRunner on Azure databases (it was broken by the check for LocalDB, because Azure returns NULL instead of 0).
  • [WPF] One of the TabbedShell constructors was mistakenly restricting menubuilders to a core IServices instead of a WPF IServices.

v205.0.0

  • [IMPORT] Recalculator no longer swallows internal exceptions without reporting them.

  • [IMPORT] Recalculator now uses the ImportRetriesPerBatch setting instead of retrying forever.

  • [IMPORT] Fixed bugs and improved performance when using Recalculator with async persistence.

  • [IMPORT] Fixed an unobserved task in ImportData when the Options.ImportUnbatched flag is set. This led to a race condition in tests.

  • [LINQ] Query support has been rewritten to use a database-agnostic IR. Query translation is now more robust, particularly when it comes to sorting and paging data; it should now be possible to use IQueryable for the use cases which previously required IEntitySet and its GetPage() method. Additionally, the following query patterns are now supported across all backends:

    • .Cast<T>()
    • .ElementAt() and .ElementAtOrDefault()
    • .Count(predicate), the two-argument version
    • string.Concat()
    • operator + for strings
    • one-argument string.Substring()
    • operators +, -, *, / and % for numbers
    • operators == and != for Nullable<T>
    • upcasts and downcasts involving IEntity or feature interfaces like IUserProfile.
    • casts to and from Nullable<T>
    • value queries (selection of columns within entities like Foo.Query().Select(f => f.Bar))
    • reprojecting and filtering by values (Where, Select, OrderBy and predicated overloads after a column selection)
    • numeric aggregates - Max, Min, Sum, Average, including predicated overloads
  • [LINQ] Added async versions of all the materialisation operators: AsEnumerableAsync, CountAsync, AnyAsync, AllAsync, ElementAtAsync, ElementAtOrDefaultAsync, FirstAsync, FirstOrDefaultAsync, SingleAsync, SingleOrDefaultAsync, ToArrayAsync, ToDictionaryAsync, ToListAsync, ToLookupAsync.

  • [LINQ] As an alternative to materialisation, added .AsReadOperation() operator. This can be used to convert IQueryable<TEntity> into readops which can be batched together or saved for execution at a later date. AsReadOperation returns a type with methods for generating the equivalent readop to any of the materialisations, like:

    MyEntity.Query(context).Where(e `=>` someCondition).AsReadOperation().Count()
    or MyEntity.Query(context).Select(e `=>` e.SomeOtherEntity).AsReadOperation().AsEnumerable()
    or even predicated forms like MyEntity.Query(context).AsReadOperation().All(e `=>` someCondition)
    

    AsReadOperation works even on queries with a null context, though you may need a context to access PersistenceService to create a query in the first place!

  • [LINQ] Added a .Select(RelationshipInfo) overload, which is equivalent to either Select or SelectMany as appropriate. This is useful for nongeneric IEntity logic and for generating batch operations.

  • [LINQ] Added an .OrderBy(PropertyInfo) overload, along with OrderByDescending, ThenBy and ThenByDescending.

  • [LINQ] Arbitrary queries can now be frozen with the new .Freeze()/.FreezeAsync() operator. This produces an IFrozenQueryable which has a known Count property and the same stable-membership semantics that IEntitySet had, as well as the same optimisations for entire-table freezes. Unlike IEntitySet, it can be re-queried, allowing arbitrary searches within the frozen set.

  • [LINQ] Full interoperability with other LINQ providers - all the new IQueryable extension methods can be used on non-entity queries, and non-entity queries can be provided to framework methods which take IQueryable. For example, you could supply List<EntityType>.AsQueryable() to UI widgets and ExportService - or call List<EntityType.AsQueryable().Relate(someOtherEntity).AsReadOperation() to generate ops without access to framework services.

  • [LINQ] EntitySpecification has a new Apply() method, which adds the specification to any IQueryable.

  • [ORM] Added static method GetByIDAsync() on generated entities with GetByID().

  • [ORM] Cut down the set of read operations to a much simpler group of primitives, most now based on querying. The following readops have been removed: CountByType, GetByID, GetByQuery, SelectByRelationship, SelectByType, SelectByFrozenQuery. The set of read methods on PersistenceService has been accordingly reduced, and all remaining methods now have async versions.

  • [ORM] Removed IEntitySet; APIs which used to require an IEntitySet accept either IQueryable or IFrozenQueryable (mostly the former). Foo.GetAll() still exists for backwards compatibility, and now produces a cached frozen query; Foo.Query(), which does not require a database call should be used instead for most purposes.

  • [ORM] IOwnedSet is now a subtype of IFrozenQueryable instead of IEntitySet, and the concrete EntitySet has been renamed to OwnedSet. Its purpose is now limited to mutable, change-reporting collections.

  • [ORM] Improved support for dynamic programming using IEntity instead of concrete entities. CreateQuery() no longer requires generic parameters, and all the new query features work with IEntity and .Kernel. IEntityInfo now has extension methods for GetByID[Async], GetAll[Async] and Query, which are equivalent to the static methods on generated entity types.

  • [ORM] EntityCollectionProperty is now an IFrozenQueryable and will be searched/paged directly from the database if not already present. No collection APIs perform lazy loading anymore, so the set will only be fully loaded if modified or if EnsurePresent/EnsurePresentAsync is explicitly called. The collection's OriginalValue is also queryable.

  • [ORM] Removed the enum flag Cascade.HiddenRelationships, which was used to delete entities with non-navigable relationships by force-loading the whole thing. Force-loading is no longer possible at all for collections, so we will never accidentally materialise something like LandgateAddressType.LandgateAddresses.

  • [ORM] Added Options.DisableSyncReads for debugging application performance issues - it will throw on blocking persistence calls. Don't leave this on in production!

  • [SQL] The SQL Server backend now emits better DML from the new IR. The generated SQL used to fit queries into a one-size-fits-all pattern, but is now capable of omitting features like grouping, ordering and subqueries when not required. A simple read like Foo.Query(context).First(f => f.Name == "Name") will now produce simple SQL like SELECT TOP 1 <columns> FROM [Foo] WHERE [Name] = 'Name'.

  • [SQL] Any() and All() will now emit an EXISTS clause instead of counting rows, making it efficient to do existence tests for large queries.

  • [SQL] Improved MigrationRunner support for LocalDB.

  • [SQL] The types generated by the SQLPersistence template have been simplified and given caches to improve row-reading performance.

  • [SQL] Improved performance of ReportAutonums and ReportVersions readops, which are executed after each save.

  • [WPF] List screen threads are now 'visible' to the threadpool for better scheduling.

  • [WPF] Collection cells in List screens now use querying to load the top few values for all collections, rather than displaying a count when the collection is too large.

  • [WPF] EntitySelectorModel, the thing which uses a zombobox to look up entities, will now perform its searches in the database using the supplied IQueryable. Previously this was only possible for GetAll() sets, and other kinds of set would result in loading the whole set into memory in order to search it.

  • [WPF] Now that async reads are possible in most cases, The.WPF has been audited to find and replace code which was starting threads or loading data synchronously. Most cases should be gone, improving performance and http-compatibility of all generated screens.

  • [WPF] Collection properties now implement INotifyCollectionChanged, and can be bound directly to UI.

  • [WPF] TabbedShell's main window is now opened during BuildAsync(), rather than when the shell is instantiated - this has the effect of fixing bugs where the WPF runtime was not correctly customised or themed unless you used a splash screen.

  • [WPF] Boolean fields in sections will now be subtitled as a 'flag name' instead of just True/False.

  • [WPF] Bugfix: VirtualisedSet's indexer and LoadData method running concurrently could cause an appliction-crashing IndexOutOfRangeException in some situations.

  • [WPF] Namefix: VirtualisedSet is now VirtualisedList. It's an IList, not a set.

v204.5.2

  • [ORM] Bugfix: Excel export sometimes failed to calculate some properties.

v204.5.0

  • [SQL] Bugfix: If given enough queries to require multiple batches, SQLWriter would run the last batch multiple times using the parameters of each batch in turn, instead of each batch once using its own parameters.
  • [WPF] The levels of logs emitted by AutoUpdater have been increased, to Information for general progress information and Warning for retries. The retry warning should now also include the exception stack trace.

v204.4.9

  • [SQL] Fixed MigrationRunner bug determining the base version's sequence number when versions are noncontiguous.

v204.4.8

  • [SQL] MigrationGenerator now understands that attributes are effectively transient if contained within a transient entity.
  • [SQL] MigrationGenerator tracks triggers with greater precision and may create/alter/remove them at slightly more optimal times.

v204.4.3

  • [SQL] SQLImportFormat no longer requires a schema (it's "dbo" if none is provided).
  • [SQL] SQLImportFormat can now import from int8, int16, float and double columns (as long as the floating-point numbers will fit in a decimal).
  • [SQL] SQLImportFormat now detects and ignores system tables.

v204.4.2

  • [WPF] Bugfix: Loose xaml outputs in bin/ and obj/ were getting included into projects on second and subsequent builds.

v204.4.1

  • [WPF] Bugfix: Sorting a list by a column with a non-unique column will no longer error out.

v204.4.0

  • [MODEL] The editor will no longer crash if you invoke the Add Attribute command multiple times on a section node.
  • [MODEL] Fixed optimiser bug combining a series of already-optimised change events - bits of them could get lost. In practice, this happened when manipulating Versions in the editor.
  • [MODEL] ChangeEntityV2 events now correctly remove remove entity subclasses from the snapshot if an entity's Superclass is set to "".
  • [ORM] We've reached the next stage in deprecation of inheritance: inheritance support is NO LONGER TESTED. Runtime support still exists in DCES and, when not using migrations, in SQLES, but it WILL break at some point. Please remove all inheritance from your models.
  • [SQL] Migrations now have feature parity (apart from inheritance) and are covered by the full test suite. New apps should be created using Migrations.sql or .theSchema, rather than CreateTables/Indexes/Triggers.sql.
  • [SQL] MigrationRunner now cleans out the _Query and _QueryEntity tables if they've accumulated junk. This is an alternative to the SQL Agent job, which isn't supported on Azure.
  • [WEB] UpdateController now provides a /get route which will download the latest update zip. (This is in addition to the existing /get/somespecificupdate.zip)
  • [WPF] Display screens that are loading for the first time now have a title of e.g. "Display Foo Bar" (using the entity's Caption) instead of "Display FooBar" (using its Name).
  • [WPF] ListColumn now has a public constructor suitable for writing copier methods (e.g. "WithFoo").

v204.3.0

  • [ORM] Added low-level async read support in IEntityStore and IEndpoint. ExecuteReadsAsync() coexists with ExecuteReads() rather than replacing it; reads are a lot more complex than writes and we aren't trying to replace all APIs at once. This does however have an immediate performance benefit on the server side of a RemoteEntityStore, because it can execute the readop batch asynchronously there even if from the client's point of view their own call was synchronous.
  • [ORM] PersistenceService now has ReadAsync, as well as async versions of the convenience methods SetFromType and SetFromQuery. Built on top of these are the higher level operations T.GetAllAsync(), IQueryable<T>.ToSetAsync() and TSpecification.ToSetAsync().
  • [ORM] WebEndpoint now has constructors which don't require a preconfigured HttpClient, which makes it clearer that it takes ownership of any client you do give it. It exposes HttpClient and ServicePoint members which can be configured externally after construction to tweak its network usage.
  • [SQL] In version 168 we split the SQLReader and SQLWriter types into ImmediateReader/Writer and BufferedReader/Writer implementations. Immediate was the original, which executed each read/write operation as it visited them; Buffered is the newer version which produces batches of fused queries with far too many parameters. Buffering mode has been the default for around a year, but we kept the old code for reference and in case of bugs. It's now been removed and the 'buffered' types have been re-renamed to SQLReader/Writer.
  • [SQL] The AST produced by query translation is now less T-SQL specific and has been moved to The.Core. This is necessary but insufficient to support more RDBMSes.
  • [WPF] The refreshes of search screens, list screens and reminders sidebars triggered by loading entities now take place on the next dispatcher frame, so that they don't block the work which triggers them.
  • [WPF] SearchController is now much closer to free-threaded. Its data-loading methods are explicitly async and fewer of them are restricted to dispatcher-only.
  • [WPF] ListController and the various ways to get a list controller through ScreenService now take an async getEntities function - Func<Task<IEntitySet<T>>> instead of Func<IEntitySet<T>>. If you already have an entityset and just want to pass it in there are new overloads for that purpose; otherwise, use the new GetAllAsync() and ToSetAsync().
  • [WPF] Bugfix: Entity selectors would sometimes incorrectly ignore custom choice sets.

v204.2.1

  • The.Tool version still wasn't working, because the new CommandLineParser reserves "version" for its own use. Now it's The.Tool setversion.

v204.2.0

  • The.Tool version wasn't functioning at all!
  • [ORM] Session timestamps were being serialised as local dates - this is correct for most of our data, but these ones must be universal dates instead so that the client and server share an understanding of when a session will expire.
  • [ORM] Fixed reentrancy bug in RemoteEntityStore causing hangs when attempting implicit connection (no existing session, but authentication assumed rather than checked) on a thread-affine sync context.
  • [ORM] Authorisation checks now trap and report errors accessing the authoriser; this results in an uncached unauthorised state, so you can try again later.
  • [ORM] Now that login is less of a black box, the old magic/implicit behaviour of deferring server checks to persistence time is unhelpful. When using a non-authoritative authenticator, SecurityService CreatePrincipal() will return auth failures when the backend cannot be reached or cannot verify auth for some other non-security reason. This short-circuits a lot of needless work which might then be attempted by an application which is locally authenticated (has a token/username/windows account) but not connected (so its pubkey/password/sql integrated security can't be verified).
  • [WPF] TabbedShell's BuildMenu function now gets a The.WPF.IServices, not just a The.IServices.
  • [WPF] OnInit functions supplied to TabbedShell or MiniShell now have error handling.
  • [WPF] Deepened session integration - all contexts created by the The.Core which the The.WPF owns will now use the CurrentPrincipal. It was actually quite difficult to get such a context (since your IServices is usually The.WPF.IServices) but you could do it if you saved your core Root somewhere.
  • [WPF] ISurface.HandleErrors and HandleErrorsAsync now support being called from non-dispatcher threads. If an error occurs and they need to report it on the surface, they'll marshall that reporting to the dispatcher on a future frame.

v204.1.0

  • [ORM] The Cutoff and Ordering properties on some readops now have sensible defaults.
  • [ORM] DateTime serialisation is marginally faster.
  • [ORM] CSPKeyProvider can now detect when no USB token is attached and provide an appropriate error message.
  • [ORM] Errors reading a PKI key or a username/password are now caught earlier, producing more readable errors by wrapping them in fewer layers.
  • [WPF] RecentItems sidebar doesn't try to verify pins against the database unless/until a user is logged in.
  • [WPF] Fixed nullref in SessionService.Logout() when no OnLogout function was supplied.
  • [WPF] When using AutomaticLogin, the login during startup now takes place on a background thread for better shell responsiveness.
  • [WPF] WPF session now integrates with the ScopedContext mechanism used in The.Core to provide one-use contexts to plugins, reducing hits on the auth system.

v204.0.0

  • The.Tool check now actually checks license signatures instead of just printing them out - at least for V2 and V3 licenses. V1 requires some weird internal LicenseService stuff.

  • The.Tool benchmark now has serialisation-format benchmarks and new running options.

  • [ORM] Added PersistenceService.CountByType() (in an extension method); this exposes a simple API for the existing CountByType readop. Sometimes you just want to know how many of a thing there are and don't want to construct a typed LINQ query or freeze a set.

  • [RPC] The persistence protocol has been redesigned to improve performance and reduce bandwidth usage. There are a number of small breaking changes to the dynamic data types in The.Persistence; none of it affects the high level entity-based API, but it will impact applications which are using dynamic code to do things like implement generic screens.

  • [RPC] Fixed errors using compound values like IEnumerable<int> in cross-platform LINQ queries - queries with a .NET Framework client and a .NET Core server.

  • [RPC] Removed the two-phase serialisation of LINQ expressions, improving query serialisation performance. The ToSurrogate() mechanism now produces serialisable objects from arbitrary expressions without implicitly requiring a preprocessing step.

  • [RPC] Core valuetypes like Guid and DateTime are now represented as large integers instead of strings.

  • [RPC] Dynamic entity rowdata has been split into CompleteColumns and PartialColumns types, with minimised use of dictionaries. Inserts and selects always return the full row, so they use a simpler array instead of repeating the keys for every column.

  • [RPC] Dynamic attribute values (the datatypes handled in The.Values) are now boxed manually rather than relying on CLR autoboxing, giving us control over memory layout for serialisation.

  • [RPC] Added gzip compression to JSON and XML SerializationFormats, reducing bandwidth 10x-100x depending on the type of operation (20x is typical).

  • [RPC] Added SerializationFormat.MsgPack, a binary format which uses even less bandwidth (another 10x smaller in some cases) and encodes/decodes up to 20x as fast. This should be used by default in new applications and may eventually become the only option.

  • [SEC] Various improvements in order to make it feasible for apps to use manual login management, rather than allowing themselves to be automatically logged in when persistence first occurs.

  • [SEC] Being logged out at shutdown no longer hangs the app.

  • [SEC] Preferences are flushed on logout.

  • [SEC] Preferences are no longer loaded before login if explicit logins are being used (Options.AutomaticLogin = false).

  • [SEC] IPreferenceStore now supports keeping preferences for multiple different users. For AppDataPreferenceStore this takes the form of an optional {Name} pattern in the filename (default has changed from Settings.xml to Settings-{Name}.xml); EntityPreferenceStore just saves it in each user's IUserProfile.

  • [SEC] It wasn't possible to change Options.PreferenceSaveInterval due to an accidental "internal set;".

  • [SEC] SplashScreen delegate is now guaranteed not to be invoked until the shell model is initialised (which includes user-specified OnInit delegates and the default implementation of autoupdate); this usually happened by accident but it was a race condition. As a reminder, the purpose of this delegate is to tell the shell whether to display its main window yet, so the race condition could cause the splash screen to go away prematurely. It also rendered it an unsuitable place to call SessionService.Login(), since an initial login might already be in progress.

  • [SEC] Added Builder.OnLogin and OnLogout methods which let you register a function to run once the CurrentPrincipal is successfully changed by SessionService. These methods should generally be used instead of the PrincipalChanged event, which is difficult to use correctly if you aren't implementing an IShell.

    The OnLogin function is the place to put post-initialisation code which requires functioning database access and therefore an authenticated user; by default this will happen once at startup, but will also execute whenever an app uses manual session management functions. OnLogout isn't as useful since the framework already does things like close surfaces and reset sidebars automatically, but it's there in case you need it.

  • [WPF] Added TestShell.ConfirmModal.

  • [WPF] EntitySelectorModel bugfix - the caching was preventing dropdowns from reopening.

  • [WPF] Improve performance of inline reference fields in inline lists without an overriden choices set.

v203.0.0

  • [ORM] The ExecuteWrites() methods on IEntityStore and IEndpoint have been replaced with ExecuteWritesAsync(). Whenever possible this is 'true' I/O async, which returns its thread to the pool rather than consuming a new one.
  • [ORM] The Save() methods on IEntity and IEntityContext have been replaced with SaveAsync(). UI code which was wrapping saves in Task.Run() can remove it and save up to two threads.
  • [ORM] OnSaving and OnSaved hooks now have OnSavingAsync and OnSavedAsync alternatives.
  • [ORM] RemoteEntityStore defers its async writes to IEndpoint, and ultimately (in the case of WebEndpoint) to HttpClientHandler.
  • [ORM] DataContractEntityStore completes synchronously when operating in memory, and uses the threadpool if writing to disk.
  • [ORM] PreferenceService no longer uses lazy loading - the current user's preferences are loaded once at initialisation time and, as before, flushed regularly or on dispose.
  • [ORM] Fixed a bug using EntityBase.Logger in overrides or calculated properties during entity construction.
  • [ORM] EntityContext.Get<T>() no longer throws if it doesn't contain an entity - like the dynamic Get(), it returns null.
  • [SQL] SQLEntityStore uses ADO.NET async I/O (for writes).
  • [SQL] BufferedWriter no longer flushes query batches unpredictably if it generates too many statements during a large batch; all batches are deferred to ExecuteAsync() (formerly Execute());
  • [SQL] Removed IDatabase.GetTransactionAsync() and ITransaction.CommitAsync(), which were never natively supported.
  • [WPF] Many public methods are async due to their modals or datastore interactions (save, load, tryclose, etc). These were inconsistently named, some using an -Async suffix and some not. Public async methods are now more uniformly suffixed. An exception is the Wizard DSL, where everything is async and changing the names would interfere with a lot of existing code (as well as being misleading - async is being used as a form of yield, not in order to await some data).
  • [WPF] Lookup fields which present filtered entitysearches in a ZomboBox used to re-execute the search even when the filter hadn't changed, leading to a needless delay in opening the dropdown. The latest search result is now cached.
  • [WPF] ShellCommand now has Func<Task> constructors which take care of providing an error-handed async WPF event context.

v202.6.1

  • [TEST] Added The.Xunit.TruthTableAttribute. Specifying [TruthTable] on a [Theory] will run the test with every combination of boolean parameters.
  • [WPF] Added ZomboBox.SelectedItemChanged event.
  • [WPF] ZomboBox now selects all on click-in more reliably by allowing the current dispatcher frame to settle.
  • [WPF] ZomboBox now selects all on click-in if AllowCustomText is false, because in that case what you want to do is start a new filter.
  • [WPF] ZomboBox now reselects all after picking an item with the mouse if AllowCustomText is false, and positions the caret at the end if it was true. It used to put it at the start, which is helpful to nobody.
  • [WPF] ZomboBox no longer hooks the Home and End keys to move through its dropdown list - these are too convenient for text entry. Page Up and Page Down still scroll the list.
  • [WPF] Lookup fields containing ZomboBoxes supply a search filter which lists entities matching the text you typed in. This used to return no results - and thus an empty suggestion list - if your search had no matches; now it will return all results instead of none, as if you hadn't entered a filter at all.
  • [WPF] Lookup fields containing ZomboBoxes will sometimes choose to display a noneditable LinkBox and the option to switch into zombo mode with a [...] button; when you click ..., it doesn't immediately open a dropdown, which is desirable behaviour. What was undesirable was that it made it particularly HARD to open one - you basically had to lose and then regain focus. Now, using the navigation keys (up/down/pgup/pgdown) will open one immediately if you're in that state.

v202.6.0

  • [ORM] IUserProfile now has some useful extension methods in namespace The.Components.
  • [ORM] PasswordAuthentication and WebAuthentication now expose some public static bits for components that want to interop with them.
  • [SQL] Query translation now supports .ToUpper() and .ToUpperInvariant().

v202.5.3

  • [WPF] AutoUpdater has better diagnostics, and no longer hangs startup if unable to contact the server.

v202.5.2

  • [WEB] Actually, the problem was not referencing TypeScript per se but the inclusion of a tsconfig.json in the nuget package.

v202.5.1

  • [WEB] The.Web no longer exports its PackageReference to Microsoft.TypeScript.MSBuild.

v202.5.0

  • Removed "The" branding from solution (another step toward Instagile?) and split into two.

    • framework.sln is the existing file, modernised slightly - it can now be opened using vscode or other omnisharp-based editors, even on mac or linux.
    • framework.xplat.sln is a subset which can be built using dotnet build on mac or linux. It excludes WPF, Office integration and VS integration.
  • Moved projects into subdirectories to match the virtual folders defined in the sln file. This is so that people using filesystem-based editors like Sublime Text or Visual Studio Code get the same layout as IDE users.

  • [MODEL] Reverted the stricter snapshot enforcement (decimal lengths, name clashes) implemented in 202.1.0 for existing events and added new event versions (ChangeAttributeV7, CreateAttributeV5) which enforce this. Saving model files will upgrade to the new events and attempt to fix bad ones.

  • [MODEL] Added event sequence debugging functions .ToCode() and .ShakeTree() on IEvent and on IEnumerable<IEvent>. These are for diagnosing edge case bugs which occur in very large and complex histories.

  • [MODEL] Architectural improvements to StemOptimiser - more granular tracking of inter-event dependencies, integration of total event cancellation with the dependency system, treating internal minimality as a cost to be paid for undo, rather than a helpful input...

    Better optimisations are now possible, and a number of bugs have been fixed, including: * Too-eagerly combining ChangeEntity events when some affected ordering and others didn't. * A class of bugs where a sequence like (Move attribute into section -> Reorder section -> Delete attribute) would remove the Move but leave the Reorder intact and invalid. * Sequences like (Create prop 1 -> Create prop 2 -> Reorder prop 2 -> Reorder prop 1) would effectively change the ordering by merging down to 2 events instead of 3. * Delete events would cancel out earlier Create events in situations where their temporary lifetime had influenced ordering (which is imperative). * CopyAttributes events set up an internal snapshot structure which was inefficient and could not be detected as safely optimised. * ChangeEntity events which set DefaultSort were not dependency-tracked, so they could be merge-reordered before the property to which they referred.

  • [MODEL] Editor bugfix: you couldn't move properties into sections which were created later than the property.

  • [ORM] ByteProperty.Compare used p/invoke in a way which wasn't compatible with 32-bit windows or with linux/mac.

  • [ORM] CultureInfo wasn't specifying am/pm formatting precisely enough for linux/mac compatibility.

  • [ORM] License signature now canonicalises newlines (to windows CRLF) for linux/mac compatibility. This was actually the key blocker to running almost any framework code cross-platform!

  • [ORM] The IDatabase abstraction, which is not specific to MS SQL Server, has moved from The.SQLServer to The.Core. It was already in its own namespace, The.SQL; we just hadn't gotten around to fully extracting it.

  • [ORM] The query methods on IDatabase now support a per-command timeout. Execute methods already did.

  • [ORM] DbDataReaders provided to IDatabase mapping methods are no longer guaranteed to be rewindable - CommandBehavior.SequentialAccess may be used as a default internally, and if so then the datareader will be forward-only. This just means that you should call row accessors in order, e.g. row.GetInt32(0) before row.GetString(1) and not the other way around.

  • [TEST] Fixed some linux/mac test issues - path separator differences, newlines, etc.

  • [TEST] The.Reports.Tests, The.Model.Tests, The.Core.Tests and The.Web.Tests now pass on MacOS (10.12.6) and Linux (Ubuntu 14.04).

  • [TEST] The.SQLServer.Tests may or may not work; it builds, but we can't run the tests because they depend on LocalDB.

  • [TEST] Removed The.Xunit.ContractFact/ContractTheory - this mechanism was used heavily for framework tests and occasionally for app tests to work around limitations in Visual Studio's test explorer. The new 'hierarchical' test explorer introduced in Visual Studio 2017 15.something now supports inheritance natively and gives us a better OOB experience than continuing to have a custom definition of a contract.

  • [WEB] Modernised TypeScript version and build process.

  • [WEB] The.Web is now based on ASP.NET Core 2.1 (up from 2.0).

v202.4.0

  • [ORM] DocumentBase now has abstract methods for the properties shared between FileDocument and ImageDocument.
  • [ORM] ExportService has been generalised from PropertyPaths to operating on IColumn objects. PropertyPaths are columns, but so are PropertyInfos; you can create a plain Column with fixed data, or use combinators to relabel or remap column data.
  • [SQL] Improved MigrationRunner's validation of which datafixes have and have not been run.
  • [WEB] Made UpdateControllerBase slightly easier to override and mock.
  • [WPF] FileDocument now has the same Save/Open extensions as ImageDocument, which display progress (or at least a progress bar) on a surface using a modal screen.
  • [WPF] FileControl and ImageControl have greatly improved error handling.
  • [WPF] Deployment build feature now creates the target directory first.
  • [WPF] Bugfix: If you clicked on the exact centre of the disclosure triangle in a MultiCommandButton, it didn't work!

v202.3.3

  • [SQL] More logging for MigrationRunner.
  • [WPF] More logging for AutoUpdater.
  • [WPF] AutoUpdater can now handle having multiple old copies of a process left around in memory (by waiting patiently for them all to exit).

v202.3.1

  • [SQL] Improved DataFix api - instead of a sql batch to blindly run, you now get to specify code to run against an IDatabase.

v202.3.0

  • [MODEL] The.Tool no longer requires an output filename; if one is not given it will generate to stdout.
  • [MODEL] Introduced .theLicence v3. The.Tool can now generate v3 licences (and does so by default). In v3 licences, modelhash licensing no longer encodes the full relative path to the model file, only a filename. It also uses a version sequence number instead of an event index as the hashing point, permitting retcons and optimisation. The.Tool will use the latest version by default or a specified version name/number.
  • [MODEL] ModelSnapshot now has AllEvents property as well as the existing IncludedEvents. IncludedEvents are the events contributing only to the latest version, whereas AllEvents are.. all.. of the events.
  • [MODEL] When HistoryEditor deletes a past version, it now runs optimisation to combine the event sequences before and after that version. This is important for generating minimal migrations without a bunch of sp_rename commands.
  • [SQL] Added new concrete IDatabase implementation LocalDatabase. LocalDatabase instances are IDisposable representations of temporary LocalDB databases, created on construction and deleted when disposed or finalised. While it exists, a LocalDatabase has a random unique name - they're for testing, not long-term data storage.
  • [WPF] Added control LinkBox, a textbox-like view which contains either an entity link for master data or bare text for reference data and follows the theming conventions of other 'box' controls. It's intended to be a useful primitive for implementing fields which in some way select or edit an entity.
  • [WPF] Fixed lookup inline reference fields displaying an editable selector (zombobox) at some times when they shouldn't have been editable.
  • [WPF] Improved the appearance of lookup & value inline reference fields.
  • [WPF] Improved the appearance of gridsplitters (the resize handle) in multiline text fields, inline collection fields and sections.
  • [WPF] Added ISurface.ClearNotifications().
  • [WPF] TabbedShell sidebar handling was incorrect in a number of ways; removal then re-add didn't work, and you couldn't register sidebars in OnInit functions. ISidebarController interface has become slightly richer to support fixes.
  • [WPF] Added SidebarService.HasRegistration<T>() for apps to inspect whether a sidebar exists (it's just a nonthrowing version of GetInstance).
  • [WPF] Removed the misleading Options.InitialEnvironment, which no longer has any effect - core Options.EnvironmentName is used instead!

v202.2.1

  • [SQL] MigrationRunner now has a configurable per-batch execution timeout, defaulting to 5 minutes (up from the basic 30 seconds allowed by ADO.NET).

v202.2.0

  • [SQL] MigrationGenerator primary key and index names now match the output of CreateTables/CreateIndexes.
  • [SQL] MigrationGenerator now renames keys and indexes when a table is renamed so that future DROP or ALTER statements are feasible.
  • [SQL] Added support for "DataFix" parameters to MigrationRunner. These fixes contain handwritten SQL, which can be targeted to run before or after a given migration.

v202.1.0

  • [MODEL] SnapshotBuilder now enforces that if a string is changed to a decimal its MaxLength must be reduced to something Decimal supports.
  • [MODEL] SnapshotBuilder now enforces attribute name uniqueness within an entity. To facilitate this, the editor appends 2, 3, etc to new attribute names if necessary.
  • [SQL] Added The.SQLServer.Schema.MigrationRunner, which actually executes migrations. The main method is RunMigrations, which takes a SchemaFile as input and optionally a 'base' migration (by sequence number or name) which is assumed to be the current state of the database. It has a reasonable amount of info and debug-level logging and understands how to batch up DDL when possible.
  • [SQL] MigrationGenerator now knows how to drop and recreate indexes when necessary to alter columns.
  • [SQL] MigrationGenerator now supports changing an attribute's name and transience in the same event.
  • [SQL] TriggerGenerator was refactored out of preexisting trigger code, so it still had support for inheritance. This wasn't useful (as the rest of the new DLL does not support inheritance) and has been removed.
  • [SQL] TriggerGenerator was generating incorrect code for AFTER DELETE triggers on HasAudit entities - attempting to reference INSERTED instead of DELETED in some cases.
  • [SQL] Setup scripts now create an application_user database role for convenience purposes; this role has SELECT, INSERT, UPDATE, DELETE and EXECUTE, which are the necessary permissions for a framework application at run time. This role can't be used to run migrations or do other DDL.

v202.0.6

  • [SQL] DEFAULT syntax wasn't quite working out (I was thinking of the pgSQL version). Modifying column nullability now uses explicit constraints and/or the UPDATE statement as appropriate.

v202.0.5

  • [SQL] MigrationGenerator was producing incorrect DDL for ChangeModel - it didn't include the column datatype.

v202.0.4

  • [SQL] Generated schema now includes a _Migration control table recording which migrations have been executed. The Migrations.sql script generated by Migrations.tt will fill in this table, and consumers of .theSchema can refer to it.

v202.0.3

  • [ORM] Now that obfuscation is enabled for .NET Standard builds of The.Core, XML serialization was failing when used between netfx client and corefx server (our most common use case). This was due to custom DataContract-defined serialisation of certain types which involved private variables serialised as DataMembers; tests don't catch this because they run within a single framework, so consistent renaming doesn't break them. The obfuscator has been configured to recognise this pattern and XML serialisation works again.
  • [ORM] JSON serialisation has never worked between corefx and netfx either. This was due to the Box<T> mechanism we use to implement dynamic datarows; while Box was successfully allowing the various primitives to be serialised with typeinfo, it still referred via generics to System.* types, which have different assemblynames in corefx. Instead of generics we now use a small number of trivial wrapper classes, which enables JSON and also reduces serialisation bandwidth because they're all known (assembly-local) types.
  • [WEB] WebAuthentication now permits anonymous authentication by default - you can still disable it in Options, but really it's something for IIS and ASP.NET Core auth to handle.

v202.0.2

  • [ORM] Fixed serialisation of batches of read or write ops with a covariant type - like the GetByID[]s produced by the new RecentItemsController feature. This was affecting both XML and JSON remoting methods.

v202.0.1

  • [MODEL] Added The.Utility.DelegateComparer and SemVer class for version comparisons.
  • [WEB] AutoUpdate server now correctly compares version components using numeric (for release parts) or alpha (for prerelease parts). Previously, 1.0.0.9 was considered newer than 1.0.0.10.
  • [WPF] AutoUpdate client now supports semver versions like 1.0.0-beta.
  • [WPF] Formerly static AutoUpdate is now AutoUpdater and has logging capabilities.

v202.0.0

  • This release includes a revamp to IServices, the top-level framework APIs. In order to simplify and consolidate the available APIs, there are a number of smaller breaking changes. For the most part they've just been moved around rather than changing names or functions, but see below if you can't find one. In all packages, the remaining '-Manager' classes are now suffixed '-Service' and the FooService returning properties have been renamed to just Foo.

  • The .NET Standard build of The.Core is now obfuscated. However, the .NET Standard build of The.Model is no longer obfuscated.

  • Microsoft.Extensions.Logging.Abstractions dependency increased from 2.0.0 to 2.1.1. This package has no dependencies of its own, so it is unlikely to be an issue for applications.

  • [MODEL] Added a new option to the Clean Model function: compress event history. This runs optimisation on each of the inter-version event sequences, potentially reducing the model size and initial migration complexity.

  • [MODEL] App node now displays ephemeral version timestamps in the local zone instead of UTC.

  • [MODEL] Attribute snapshots now declare whether an attribute is part of an index or the primary key; this is not yet possible to model with events, but is set by the some of the builtin attributes and used by SQL migration to define tables. Primary-key attributes cannot be nullable.

  • [MODEL] Added Serialise.ReadString<T>().

  • [ORM] Renamed FeatureService and The.Features to ComponentService and The.Components, a slightly less generic name. Unless and until we change the name of the design-time equivalent, the idea is that a 'model feature' is implemented by a 'runtime component'.

  • [ORM] ConversionService no longer needs any runtime state, and has been replaced with a static class Conversions.

  • [ORM] Moved the various logger-creation methods on Core IServices to the new LogService.

  • [ORM] Preferences are a single-user concept; PreferenceService loads the current principal's settings once and caches them. Accordingly, access to PreferenceService has been removed from The.IServices, but added to The.WPF.IServices (which maintains a single-user session) and to The.Web.IServices (which creates a per-request scoped session).

  • [ORM] SecurityService.CreatePrincipal() now has better fast-path checks to avoid making remote connections when using an IsAuthoritative=true IAuthentication such as WebAuthentication or PresetAuthentication; these authenticators guarantee that their VerifyIdentity method is capable of fully determining a subject's identity. Note that NTLMAuthentication is not authoritative, because its correctness may be deferred to remote validators of a flowed Windows identity.

  • [ORM] Improved error handling in DocumentService, which will now produce DocumentNotFoundExceptions if necessary instead of silently handling a null up the chain to blow up later. FileControl now displays this (or any other) exception rather than a generic error message.

  • [ORM] Replaced EntityBase.OnCreating with OnCreated. This will allow us to later introduce a new OnCreating which runs at an earlier point, before entity data is loaded; the current method runs once the entity is fully constructed.

  • [ORM] Added EntityBase.OnLoaded, which can be overridden to run code when an entity has been constructed from a datastore row.

  • [ORM] OnCreated (formerly OnCreating) no longer runs twice when an unsaved entity is cloned.

  • [ORM] Changed the semantics of IEntity.Delete(). This is a deliberate breaking change: value relationships will no longer be automatically broken before saving, so deleting an entity which owns other undeleted entities will produce a foreign key violation on save. Full control of which relationships to break is possible with the optional Cascade enum.

  • [ORM] EntityKernel.MarkDeleted() takes a mandatory Cascade parameter for which relationships to break. The new MarkDeletedTransitive() applies marking and cascading through Value relationships; this avoids orphans without having to manually mark children deleted first as in the Delete() workflow. Delete() is still preferred for business logic; it defers policy to the relational datastore and avoids the possibility of expensively loading non-navigable collections.

  • [ORM] Fixed a concurrency issue in DataContractEntityStore: the FreezeQuery operation was protected by a readlock, but it modifies data, so it needs a writelock. ExecuteReads now takes the lock upgradeably if necessary.

  • [ORM] The.Composition.Root is no longer IDisposable!

  • [SQL] SchemaFile now contains explicit <Batch> elements instead of expecting consumers to understand GO pseudostatements.

  • [SQL] MigrationGenerator now generates indexes as well as triggers; the triggers are still bad.

  • [SQL] Implemented migrations for events:

    * CreateEntity
    * ChangeEntity
    * DeleteEntity
    * ChangeAttribute
    * DeleteAttribute
    * DeleteEntitySection (trivial)
    
  • [SQL] SQL Agent job initialisation code no longer tries to run on Azure, which doesn't support it. This doesn't yet solve the problem of providing equivalent functionality on Azure.

  • [WEB] The.Web now has its own top level IServices. Like The.WPF, this is a layer over The.Core with added features and ASP.NET Core integrations. Composition.Builder and Root classes are available as usual, but the typical way to do initialisation is slightly different - instead of creating a Builder directly, customisation is done using methods on the IBuilder returned from AddTheFramework(). This is in line with how other ASP.NET integrations are configured, such as MVC itself.

  • [WEB] Added WebAuthentication, a new default authenticator which uses the identity information supplied by ASP.NET Core. The only remaining required parameters for AddTheFramework() are an EntityMetadataDictionary and IEntityStore, or a build function to fully customise the integration. WebAuthentication doesn't allow anonymous HTTP by default, but it can be enabled using something like this:

    .AddTheFramework(Entities.Metadata, new DataContractEntityStore())
    .Configure(options `=>` options.PermitAnonymousAuthentication = true)
    

    You can use various authentication methods via ASP.NET Core Identity, or enable simple IIS-based auth by setting "windowsAuthentication": true in launchSettings.json.

  • [WPF] Instead of starting a background thread and providing an event-like task on SessionService, WPF.Composition.Builder now has BuildAsync() instead of Build(); the awaitable returned by BuildAsync() is only completed once the application is fully available, including login and autoupdate as well as app-supplied onInit functions.

  • [WPF] Broke up and removed NotificationManager, which was just a grab-bag of random events:

    • ShellInited is no longer necessary due to the BuildAsync() feature.
    • ShellExited has moved to LoginManager, which is now SessionManager to commemorate its expanded capabilities.
    • UIPreferenceChanged was/should only be accessed through the AddWeakUIPreferenceChangedListener method, which has become an extension method on PreferenceManager.
    • EntityOpened/EntitySaved are about inter-screen communication and have moved to ScreenManager.
  • [WPF] Removed EnvironmentManager. The subscription-based dynamic environment feature was ill-conceived and unused; the only good thing about it was automatically swapping in XAML resources based on environment name at startup. The.Composition.Options now has an EnvironmentName setting which is exposed as The.IServices.Environment and provides the same feature. In The.Web this is automatically set from the ASP.NET Core environment; in WPF applications, you may want to use something like:

    .Configure(options `=>` options.EnvironmentName = ConfigurationManager.AppSettings["Environment"])
    
  • [WPF] TemplateManager was in the Screens namespace but really had nothing to do with screens; it's moved to The.WPF.Utility, and more of its methods have been made public to improve layering.

  • [WPF] Deleting child entities through Value reference/collection fields now transitively deletes their own children using MarkDeletedTransitive.

  • [WPF] Fixed bugs in RecentItems sidebar text truncation.

  • [WPF] RecentItems controller can optionally verify the existence and name of deserialised pins. This is an expensive DB operation which might occur during app startup, so it's off by default.

v201.1.3

  • [WPF] AutoUpdate now tries harder to shut down the old application, using Environment.Exit instead of Application.Shutdown (which more things hook, delay or otherwise block).
  • [WPF] RecentItems sidebar now updates text when entities are saved or when they're reopened with new text.
  • [WPF] RecentItems text is now truncated to a configurable limit (default 30 characters). The full text is visible in a tooltip.

v201.1.2

  • [WPF] Bugfix: Loading a Display screen was checking its inner Content screen's ISections' visibility, concurrently, on different threads. This is a more serious problem than it sounds as of release 201, because any lazy loads in section visibility checks (HiddenIf, VisibleIf, etc) would result in concurrent and now illegal modification of the same context.

v201.1.1

  • [WPF] Bugfix: AutoUpdate recursive content didn't install properly.

v201.1.0

  • [ORM] Added arguments to PersistenceManager.GetByID<T> which enable eager loading, optionally preloading related entities and relevant reference data in a single batch of operations. This will typically be used through the higher-level typed API, which has various overloads:

    Foo.GetByID(context, id, params RelationshipInfo[]) // loads related entities
    Foo.GetByID(context, id, params IEntityInfo[]) // loads entire sets of related data, typically reference data
    Foo.GetByID(context, id, RelationshipInfo[], IEntityInfo[]) // loads both relationships and reference data
    

    Eager loading uses a lot of bandwidth, but it's a good way to improve performance when using a high-latency backend like Azure. It's particularly useful for retrieving a bunch of related data which would be immediately accessed anyway. For example, the GetPaid 2 Timesheet screen overrides LoadEntity as follows: protected override Timesheet LoadEntity() => Timesheet.GetByID(Services.CreateContext(), ID, new RelationshipInfo[] { Timesheet.Metadata.Worker, Timesheet.Metadata.WorkEntries }, new IEntityInfo[] { Project.Metadata, Activity.Metadata } );

  • [WPF] Bugfix: automatic AssemblyInfo versioning could go a bit crazy if your msbuild properties contained Version but not VersionPrefix.

v201.0.0

  • Test builds can now be created on systems without Eazfuscator.NET installed.

  • [MODEL] New model version 6, in which the confusing 'snapshots' have been replaced by 'versions' with a stable sequence number. NamedSnapshotV1 events are obsolete; NamedVersionV2 and EphemeralVersionV1 have been added, each of which has a new Sequence property. Upgrading a <=v5 model will assign incrementing sequence numbers to its existing versions and version-terminate the file.

    The model editor creates versions on save and displays historical versions, providing functions to retcon history; 'ephemeral' timestamped versions can be upgraded to permanent 'named' versions or deleted. Sequence numbers don't change when retcons occur, making them suitable to identify database migrations. There's a new setting which can be used to disable this behaviour, but if it's turned off then migrations will only be possible between explicitly-created named versions.

  • [MODEL] No longer generate code with warnings when a model contains no entities.

  • [MODEL] LegacyRefID tags were being removed from almost every model element, but not from sections. They now go away entirely on save, and version equality testing accounts for this.

  • [MODEL] Upgrading model files no longer fails if a file happened to contain no obsolete events.

  • [MODEL] Editor: added explicit fields like "Namespace:" and "Entity name:" as well as the existing uniform node title UI.

  • [MODEL] Editor: removed display/edit support for entity inheritance.

  • [MODEL] Editor: When creating a new node, the title is focused and selected.

  • [MODEL] Editor: Added HistoryEditor.IsReadOnly dependency property to display a model without allowing changes.

  • [MODEL] Editor: "Extract reference data" command now creates less confusing names.

  • [MODEL] Extension: Errors loading a .theModel file into an editor tab or saving it back to a file are now handled instead of crashing (!) visual studio. Because this is fixed in The.Extension 201.0, version 200.0 still crashes attempting to edit v6 model files; it can still run code generation for those files thanks to the decoupled generator mechanism.

  • [ORM] FreezeQuery readops are now batched.

  • [ORM] GetVersions generic readop has been split into ReportVersions and ReportAutonums readops, which are both batched.

  • [ORM] DynamicQuery generic readop had three remaining use cases, which have been replaced by type-based dispatch to three different batched readops:

    * the existing DynamicCountQuery has become CountByQuery, which executes integer aggregates
    * the new TestByQuery executes boolean aggregates
    * the new GetByQuery is a specialised form of SelectByQuery which returns single-row batches.
    
  • [ORM] All read operations are now batchable, and IEntityStore has been reduced to three methods (ConnectAsync, ExecuteReads, ExecuteWrites).

  • [ORM] The PersistenceManager extensions in The.Persistence.Read have more consistent names. Most notably, PersistenceManager.GetAll is now PersistenceManager.SetFromType.

  • [ORM] EntityContexts use more fine-grained locking than previously and will perform better during concurrent or asynchronous saves. The new locking system enforces stricter checking for simultaneous additions of the same entity to a context on multiple threads; previously, the first added entity would 'win' and any differences in other copies of the entity would be thrown away. This kind of code will now produce a merge failure exception:

    var sharedContext = framework.CreateContext();
    var sharedQuery = Entity.Query(sharedContext);
    var threads = Enumerable
      .Range(1, 10)
      .Select((i) `=>` Task.Run(() `=>` sharedQuery.ToArray()))
      .ToArray();
    
  • [ORM] The authorisation system no longer throws when asked to check a sequence of zero read operations.

  • [ORM] Bugfix: Adding elements to an unloaded nonempty collection before later lazy-loading it resulted in the new elements being considered OriginalValues and HasChanges() erroneously being false.

  • [SQL] Implemented query translator support for .All(Func<T,bool>).

  • [SQL] Added IDatabase.ChangeDatabase(), which modifies the connection string or equivalent internal handle.

  • [SQL] Improved logging and stack traces for unexpected (caused-by-a-bug) write failures.

  • [SQL] Removed(!) query translator support for selecting values (as opposed to whole entities). This implementation was fragile and had many edge-case bugs; hopefully removing the current version will facilitate reintroducing a similar capability in the future.

  • [SQL] The Migrations template now generates two files, Migrations.sql for creating a complete database from scratch and <modelname>.theSchema for a structured description of the possible database states and migrations between them.

  • [SQL] SQLEntityStore no longer throws when asked to execute zero read or write operations. It doesn't do anything, but it doesn't throw.

  • [SQL] MigrationGenerator now has tested implementations of some events, including

    * CreateModel (initial db setup code)
    * ChangeModel (enable/disable global flags like nullability enforcement)
    * CreateAttribute (cleaner implementation than CreateTables, now supports adding columns to tables with existing rows)
    * CreateEntitySection, ChangeEntitySection, EphemeralVersion, NamedVersion (trivial, as these events don't require any DDL)
    
  • [TEST] Added The.Xunit.SQLAssert for less-brittle testing of generated SQL.

  • [TEST] The SQL test suite now creates databases on the fly, exercising the schema-creation code. Currently it's testing the old version from CreateTables/Triggers/Indexes.

  • [TEST] Tests now pass on Windows 7, as long as KB4054856 is installed.

  • [WPF] Added themeable 'ValidationDelay' property to ErrorBorder control. If this property is set to a non-null timespan in the default style, the border won't render until that amount of time has elapsed, simulating a forgiving delay of the validation process. Example of activating this feature in an application's resource dictionary:

      <Style TargetType="the:ErrorBorder" BasedOn="{StaticResource {x:Type the:ErrorBorder}}">
          <Setter Property="ValidationDelay" Value="00:00:00.300"/>
      </Style>
    

    The default delay is 400ms, same as the default SearchDelay in WPF.Composition.Options.

  • [WPF] Saving new entities from Create screens is now precisely five seconds faster (don't ask).

  • [WPF] RemindersController no longer generates empty db requests when an irrelevant entity is saved.

  • [WPF] Using the Version msbuild property to generate AssemblyInfo now works in more Visual Studio configurations.

  • [WPF] AutoUpdate now supports recursive content - previously it would only install updates with a flat layout.

  • [WPF] AutoUpdate now supports automatic downgrades and reinstallation of existing versions.

  • [WPF] ISurface.ShowNotification now supports an optional timeout after which the notification will be automatically dismissed. TabbedShell implements this for tabs and for the global notification bar.

  • [WPF] Save-completed notifications time out after a couple of seconds, configurable via The.WPF.Composition.Options.

v200.4.0

  • [ORM] Currency attributes now have a precision of 2 rather than 3.

v200.3.1

  • [MODEL] Rebranded The.Extension as 'Instagile'.

v200.3.0

  • [ORM] Invalid licenses are allowed when debugging once again, but you'll get an annoying dialog box at startup reminding you about it. They also display as Unlicensed instead of Test Only in the status bar.
  • [ORM] Added IEntityInfo.IsTopLevel.
  • [WPF] Add constructor parameter to RemindersController to allow task reminders to be displayed unsorted.
  • [WPF] MenuBuilder.Default() once again uses IsTopLevel as it originally did.
  • [WPF] RecentItemsController now limits the number of saved pins (default 20).

v200.2.0

  • [MODEL] Added IEnumerable<T> extension methods Prepend() and Append(), which are single-element equivalents of Concat().

  • [ORM] Added utility class The.Persistence.Remote.Deployment which describes a version of a client app.

  • [WEB] New controller for serving client app updates. UpdateControllerBase subclasses search for zip files with the filename pattern appname-version-environment used by deploy.targets in the webroot or a specified IFileProvider. Routes include

    /update/all - lists all available deployments which match the environment of the server
    /update/latest - returns just the newest available deployment
    `/update/get/<deployment-name>` - downloads a deployment zip
    
  • [WPF] DeploymentEnvironment packaging now includes a version number (derived from the Version/Suffix/Prefix properties).

  • [WPF] TabbedShell constructor now supports an autoUpdateServer parameter specifying a URL from which to download updates. The functions in The.WPF.Shell.AutoUpdate can be used to orchestrate this process manually rather than letting the shell control it.

v200.1.0

  • [IMPORT] Access importer now operates on a copy of the source db to avoid modifying the original file. It will compact-and-repair the copy before importing.
  • [IMPORT] New framework setting ImportRetriesPerBatch, default 0, to be used when e.g. network connection to import target is unreliable.
  • [MODEL] The.Extension should now work on machines with .NET 4.6 but not 4.7 by including the netstandard.dll facades in its package.
  • [ORM] Running under a debugger no longer bypasses licensing. This feature has bitten us too many times to be worth avoiding generating a test license.
  • [WEB] The.Web updated to latest ASP.NET Core patch release 2.0.8.
  • [WPF] The.WPF does some msbuild magic to allow its consumers to use new-style ("SDK") projects.
  • [WPF] For apps still using old-style projects, the VersionPrefix and VersionSuffix properties are now implemented with the same semantics as in SDK projects. Version, if set explicitly or calculated from prefix/suffix, will replace whatever is set in AssemblyInfo.cs.
  • [WPF] Apps can set properties SignatureSubject or SignatureHash to have an Authenticode signature generated. See sign.props for more options.
  • [WPF] Apps can include DeploymentEnvironment items; for each environment, an archive will be created containing the published client with its app.config modified to set an Environment key. See deploy.props for more options.

v200.0.4

  • [WPF] Bugfix: Temporary work-around for a bug where attempting to sort by a column if there's more than one column with that name throws an exception (eg when the Text column matches another column).

v200.0.1

  • [MODEL] New gen process now works on machines with weirder extension layouts.

v200.0.0

  • The.Framework is now The.Core. Sorry about all the PackageReferences.
  • [MODEL] The versions of The.Model used by The.Extension and The.Framework are now fully decoupled. Generating code in the editor launches a separate process, which dynamically loads the model engine from nuget packages referenced by the open solution. Template DLLs in the solution are no longer loaded into Visual Studio, even in a separate app domain; it should therefore be ok to use any future extension version on any solution which is referencing this version of the framework or a newer version.

v192.2.0

  • [WPF] Fixed hyperlinks instead of zomboboxes showing for references to reference data.
  • [WPF] Fixed zomboboxes instead of hyperlinks showing for references from reference data.
  • [WPF] Allow application developers to override the maximum suggested choice count for LookupInlineReferenceField and EntitySelectorModel.
  • [WPF] Fix sorting an inline editable list by a relationship field column causing the list to stop working.

v192.1.1

  • [MODEL] The model editor is now compatible with Windows 7, probably.
  • [WPF] When lookup references to master data are non-null (e.g. initial data entry isn't taking place), they will be displayed as a hyperlink with an edit button instead of a search/selector zombobox.
  • [WPF] Improved ui consistency of "textish" fields (multiline, reference, etc), giving them a textboxlike border.
  • [WPF] Fixed crash when middle-clicking on entitylinks which point to a null.

v192.1.0

  • [WPF] Unsaved changes now block shutdown/signout.
  • [WPF] It is now possible to override the link middle-click behaviour on lists by overriding the DoOpenInBackground command.

v192.0.1

  • [WPF] Fix list description column sometimes swapping places with the second column.

v192.0.0

  • [WPF] Fields for text attributes are now more customisable.
  • [WPF] Lists will now load their first page before their second.
  • [WPF] Reunbreak Manage Columns not allowing users to add any new columns.

v191.0.0

  • This release requires an extension update.

  • [MODEL] ModelFile.History is now an IReadOnlyList<IEvent> as well as an IReadOnlyCollection<IEvent>. HistoryEditor.History now also requires IReadOnlyList<IEvent>. In practice, both saved files and graphically edited histories are a reified buffer rather than a stream.

  • [MODEL] Combined SnapshotTemplateBase and HistoryTemplateBase into a single type which provides both modes of access to the model.

  • [MODEL] Added new event NamedSnapshotV1. This lets you name a snapshot; the optimiser will only optimise runs of events between snapshots, preserving the state of the model at each version for historical inspection. SnapshotBuilder has a new factory method which reconstructs all the named versions in an event history; these are available in the combined t4 template as a Versions property.

  • [MODEL] Added ModelSnapshot.IncludedEvents, the event sequence unique to a particular snapshot (those postdating the previous version).

  • [MODEL] Simplified templating directives - Insert is the new InsertOrReplace, and the old Insert is gone. Insert was for files that should be 'generated once' and then user-modified, but this isn't a good idea and we haven't been using it.

  • [MODEL] Editor: Removed the old fixed-columns view, now that the tree view is adequate, to reduce maintenance.

  • [MODEL] Editor: Added 'create snapshot' app command.

  • [MODEL] Editor: Fixed crashing when opening command dialogs in non-Visual Studio embeddings.

  • [MODEL] Bugfix: Closed off a race condition in undo/redo which could potentially "lose" some events. I'm not sure whether it was possible to trigger it in reality.

  • [MODEL] Bugfix: Moving a relationship between sections could confuse the optimiser, making everything very bad.

  • [MODEL] Bugfix: DeleteSection and DeleteEntity events didn't correctly remove section nodes from the snapshot, leaving it in an invalid state.

  • [MODEL] Bugfix: Rewrote the optimiser handling of Delete events for more accurate results - this covers numerous individual bugs where long sequences of events affecting some model node were later obviated by an edit which deletes that node. These bugs were rarely triggered before snapshots, but are much more common when entire models are optimised at once.

  • [MODEL] Bugfix/inconsistency: default Precision was 2 in snapshots but 3 in sql. It's now 3 in both.

  • [ORM] Improved time parsing; we can now handle three-digit 24-hour times like "845" or "010".

  • [SQL] Removed separate enablement of identity columns via the CreateTablesWithoutIdentityColumns and EnableIdentityColumns templates - this will be a concern of import, not of schemagen.

  • [SQL] Added new template, Migrations.tt. This generates sql scripts into a folder named Migrations:

    * a special _Initial_ migration, which contains the same one-time setup code generated by parts of the existing Create___ templates.
    * a migration to each versioned snapshot from the previous snapshot, converting events to schema changes.
    * a special _Current_ migration, which enacts all events from the last versioned snapshot to the final snapshot, or all events if there have been no versioned snapshots.
    

    Each migration script will contain a combination of DDL and DML to alter an existing database in accordance with the model changes made between snapshots. However, most events are not yet implemented.

  • [SQL] Removed the setUserInfo()/getUserInfo() mechanism for storing usernames in CONTEXT_INFO. This was no longer being used by persistence, and it doesn't work reliably on Azure.

  • [SQL] Bugfix: version-conflict leeway wasn't applying anymore due to incompatibility with the new authentication system (it only applies leeway to the same user's changes).

v190.0.5

  • [WPF] Fixed bugs with ListController column management, at the cost of removing the ability to modify columns in InitialiseModel overrides. We'll reenable it or introduce an alternative if necessary.

v190.0.4

  • [ORM] Improved coverage and test robustness for feature entities.
  • [SQL] Improved resolution of sub- and super-type names, fixing edge cases like Query<ISomeInterface>().Select<IAnotherInterface>().

v190.0.3

  • [LOGGING] Fix logging not working at all if no filter is applied.
  • [WPF] The "Manage Grid Columns" dialog box's Select button is now an OK button, and its tab headers are no longer as cramped.

v190.0.2

  • Removed some accidentally released changes.

v190.0.1

  • [SQL] Bugfix: CreateTables.tt and CreateTriggers.tt could raise an ArgumentOutOfRangeException if the model contained at least two entities total but less than two persistent entities.
  • [WPF] ListController no longer assumes that its columns have not been changed by overrides to InitialiseModel.
  • [WPF] ListColumn has a new WithSortPath method, which can be called with a different path to change how the column sorts or with null to disable sorting by that column.
  • [WPF] ListController has a new GetAvailableColumns method, which can be overridden to change the list's set of available columns wholesale.

v189.0.0

  • [ORM] Added support for new time formats - period-denominated times like "09.00 [am]" and punctuationless 24-hour time ("0100, "1330", etc).
  • [WPF] List fields are now referred to as columns - this reduces ambiguity caused by some columns containing fields.
  • [WPF] DisplayFormat/DisplayType is now ColumnType.
  • [WPF] The "Custom" column type is now called "Field" and is the default for all columns of editable inline lists. The new WithColumnType method on ListColumn can be used to specify a different column type, which will be respected by the view.
  • [WPF] ICF.Select can now be overridden.
  • [WPF] The FieldModal screen is now public and has been made more suitable for application use.

v188.1.0

  • [WPF] Shell menubuilder functions can now use IServices to build a dynamic menu.
  • [WPF] As well as a SplashScreen delegate, TabbedShell now supports OnInit delegates which run during startup, delaying ShellInitComplete.

v188.0.0

  • [IMPORT] Bugfix: Extracting reference data from an entity that was being deduplicated could result in a foreign key violation.

  • [ORM] Renamed IsWorthSaving() to something clearer: IsCalculated(). The meaning is inverted from its previous implementation; if an entity is 'calculated' then it has the same semantic meaning as an attribute being calculated. It is derived data which will be updated on save but is not part of data entry.

  • [ORM] ChangeNotification.AddCalculationDependencyHandlers wasn't detecting changes if a calculated property with dependencies had a non-default value before the handlers were installed but had never actually been calculated before. To avoid this problem, it now performs an immediate calculation of the tracked property, which can potentially mean an immediate ValueChanged event if it does not calculate to the default value.

    As before, try to avoid using [CalculationDependency] on expensive calculations.

  • [SQL] Bugfix: The CreateTriggers template did not escape column names, preventing the use of attribute names like Index.

  • [WPF] ValueFields are meant to update their UI if the underlying model is changed. This was implemented using a weak event handler, but incorrectly - the handler was being garbage collected pretty quickly. It still appeared to work most of the time, using an alternate mechanism of update on rule invalidation - but this doesn't work when you have no validation rules, as in the case of Duration in GetPaid. Now IValue changes are detected without resorting to validation.

v187.2.0

  • [ORM] RelationshipProperty now has NeedsSave as well as HasChanges.
  • [ORM] New entity feature: data-dependent transience. Generated entity classes now have an overridable method IsWorthSaving(); if this returns false, then the entity will not contribute to EntityKernel.NeedsSave() or to change description. The entity will still be saved if Save() is actually called - this is a way to avoid bothering interactive users with unimportant information.

v187.1.1

  • [ORM] SetOrderings can now be conveniently created from PropertyInfos.

v187.1.0

  • [WPF] Improved performance of search screen refresh
  • [WPF] ListController has a new public method GetCurrentOrdering(), which produces an array of SetOrdering equivalent to the one the list has configured in UI.

v187.0.1

  • [WPF] Bugfix: List screens would NRE if they received an EntitySaved notification while still loading for the first time.

v187.0.0

  • Dropped support for Visual Basic. Many features will still work from VB code, since it's just .NET, but anything language-specific (e.g. codegen) is gone.

v186.2.0

  • [WPF] Added public method RemindersController.UpdateAllAsync(), which forces an immediate recheck of reminders.
  • [WPF] Reminders now force their list to be non-Inline.

v186.1.2

  • [ORM] Bugfix: datetimes in entity data no longer serialise their timezones - SQL throws them away anyway.

v186.1.1

  • [ORM] Bugfix: Fixed NullReferenceException when setting a reference to null that a deep value change handler is observing.

v186.1.0

  • [ORM] Implemented DataContract query translation for feature interfaces.
  • [ORM] FeatureManager can now hand out IQueryable<IWhatever>s.
  • [ORM] Improved the performance of ProfileAuthorisation.
  • [SQL] Implemented SQL query translation for feature interfaces.

v186.0.1

  • [ORM] Lazy load of references now uses the existing context, which can be very important for performance when caching things like remote authorisation.

v186.0.0

  • [IMPORT] Add new overloads of ImportManager.CopyData with support for multiple data paths.
  • [IMPORT] Bugfix: Data import now works when using unique keys and foreign keys at the same time.

v185.0.0

  • The.Tool license subcommand no longer requires an input argument unless you're performing binary hashing, and new -l parameter can be used to set event leeway. Sample invocation:

    banana@forsyth MINGW64 /c/code/marvin/Marvin.Model (master)
    $ dotnet run -p /c/code/framework/The.Tool -- license -p "WA Police" -m Model\\Marvin.Model.theModel -l 100 Marvin.Model.theLicence
    Generating production license for WA Police
      Restriction: valid for model file Model\Marvin.Model.theModel (+ up to 100 events)
    License saved to Marvin.Model.theLicence
    
  • [IMPORT] Added new import tag The.Import.AUK which marks an attribute as being a component of a unique key for an entity.

  • [IMPORT] The import system can now deduplicate entities being imported based on an optionally composite key formed from its attributes.

  • [MODEL] The model editor now has support for specifying which attributes should be treated as part of a unique key during import.

  • [SQL] SQLImportFormat no longer has any constructor parameters; the name parameter to its Open method should now be in the form "connection string|schema name" (connection string and schema name separated by a pipe character).

  • [SQL] SQLImportFormat now provides more detail when throwing a NotSupportedException due to unsupported source elements.

  • [SQL] SQLImportFormat now imports the 'xml' data type as a Text attribute.

  • [WPF] It is no longer invalid to set export's "Maximum number of rows to export" to greater than the number of available rows.

  • [WPF] Bugfix: Fields in the Export Options window were left-aligned instead of stretching to fill the width of the window.

v184.1.2

  • [WPF] The "An ItemsControl is inconsistent with its items source." error will no longer be displayed as a notification; it will only be logged.

v184.1.1

  • [WPF] Fixed threading error in shell init.

v184.1.0

  • [ORM] Added DocumentManager. This new service replaces IServices.DocumentStore and wraps up document access methods in a convenient API, allowing the use of standalone documents without containing entities.
  • [ORM] Added an entity-based document store. If DocumentFeature is active and no IDocumentStore is explicitly registered, EntityDocumentStore will be used instead of NoDocumentStore.

v184.0.0

  • This release requires an extension update.
  • [IMPORT] ImportManager.CopyData now has a Stream-based overload.
  • [MODEL] Feature definitions are now self-contained, without needing a bunch of code split across the editor and the snapshot API. Implementations of IFeature define an entity layout and metadata; the list of available features is supplied by IEditorHost and could hypothetically be extended by applications, except that the runtime definition of features is not yet as self-contained nor as pluggable.
  • [MODEL] Added DocumentFeature, which creates entities that can be used to implement an IDocumentStore.
  • [MODEL] If AccountFeature is active and no IPreferenceStore is explicitly registered, EntityPreferenceStore will be used instead of NoPreferenceStore.
  • [MODEL] AuditFeature now creates displayable columns for easier in-app log viewing.
  • [ORM] DataContractEntityStore fix: support for feature entities with renamed attributes.
  • [ORM] Builder.WithLicenceResource will now throw a more meaningful exception if the specified resource does not exist (it previously threw a NullReferenceException).
  • [WPF] LookupInlineReferenceField and LookupSectionedCollectionField have a new canSearch constructor parameter that can be used to remove their search button.

v180.3.2

  • [ORM] Reimporting a model using automatic section splitting wasn't maintaining section IDs properly, causing complex reimports to fail.

v180.3.1

  • [WPF] Further ZomboBox refinement: changing the selected item doesn't open the dropdown if it was the user picking something FROM that dropdown.

v180.3.0

  • [SQL] Query translation now supports .ToLower() and .ToLowerInvariant().
  • [WPF] EntitySelector no longer performs filtering on unchanged text for nonreference data. That is to say, for all entity types it returns unfiltered results until the user changes some text.
  • [WPF] EntitySelector filtering is now case-insensitive.
  • [WPF] Fixed a bug causing ZomboBox to set IsTextChanged to true initially instead of to false.

v180.2.1

  • [WPF] Revert change from v170.0.0: The textbox-like part of a CollectionSelector will now execute the control's SelectCommand when clicked.

    It had some bad side effects

v180.2.0

  • [MODEL] Improved model editor save/load integration with visual studio, fixing multiple bugs - most notably, dirty checking and save-by-closing-window.
  • [WPF] Bugfix: Immutable LIRFs were not immutable.

v180.1.3

  • [IMPORT] Added a default pipeline conversion between Decimal and Currency.

v180.1.0

  • Fixed bug which was preventing packages from being generated for The.MSOffice or The.Xunit.
  • Updated to Eazfuscator.NET version 5.8 R2, enabling obfuscation for most .NET Standard DLLs.
  • [WPF] It's no longer necessary to specify 'override locations' to RegisterControllerFactory() unless screen overrides are in a different project or projects to the generated screen types.

v180.0.0

  • [DOCUMENTS] The old IDocument, FileDocument, and ImageDocument have been renamed to IDocumentMetadata, FileMetadata, and ImageMetadata respectively, and are now immutable.
  • [ORM] Document attributes have been rewritten - they now store immutable values (The.Documents.FileDocument and .ImageDocument) like other attributes do.
  • [ORM] Local IAuthenticators can now be 'authoritative', meaning that the initial result of GetIdentity() can be trusted without calling VerifyIdentity(). This improves performance in test and website scenarios. If an authenticator is not authoritative, SecurityManager will check it against the (potentially remote) entitystore the first time a principal is created for any given identity.
  • [TEST] The Animal entity has been removed from the test model; its former subtypes are still present. Each relationship to Animal has been turned into five relationships, one to each of the former subtypes.
  • [WPF] The async methods in GDIExtensions no longer use ConfigureAwait(false) - this reduces resource usage. Applications that use these methods in sync-over-async (.Wait(), .Result, .GetAwaiter().GetResult()) should wrap them in Task.Run calls to avoid deadlocks.
  • [WPF] Bugfix: ValueInlineReferenceView would not update its displayed text if its value was cleared.
  • [WPF] LookupSectionedCollectionField and ValueSectionedCollectionField's command implementations mistakenly lost their overridability when they were lifted out of SectionedCollectionFieldBase; it has been restored.
  • [WPF] Bugfix: DisplayControllers opened from a SearchController would never be editable.

v179.0.0

  • [ORM] IPreferenceStore has been changed to load all of a user's preferences as a single blob. Instead of get/set individual value methods, it now saves or loads a PreferenceDictionary on request, with a cache and lifecycle handled by PreferenceManager and settings moved to The.Framework.Composition.Options. This improves performance significantly in configurations where entitycontext creation is expensive.
  • [ORM] Some of the functions of IAuthentication have been split out into IRemoteAuthentication. Not all authenticators can be used as remote mutual authenticators (or vice versa, theoretically). This change will enable nonremote authenticators to be scoped to some sort of context (http, transaction, ui, etc), and it simplifies the construction of Endpoints by decoupling the RPC system from the security system.
  • [ORM] Building on the authenticator changes, IPrincipal no longer carries the remoting API - just authentication and authorisation for some specific identity. Acquiring and validating identities is no longer part of its purview; a simplified SecurityManager api does that for local identities, and IRemoteAuthentication is used by RemoteEntityStore to build remote identities.
  • [WPF] ValueInlineReferenceField works again - it was broken by the introduction of ZomboBox, which wasn't an appropriate control for it to use since it doesn't do any searches.

v178.1.0

  • [MODEL] Bugfix: Setting an attribute's type to Currency could cause an error to be raised if the attribute already had a precision.
  • [MODEL] New model-level commands to clean up various common issues have been added.
  • [WPF] The clock in the corner of the shell no longer displays seconds or milliseconds.

v178.0.0

  • [ORM] Context creation changes: Post-176.0, The.Framework acquires a new principal for every context, making authentication stateless. EntityContext now has a public constructor, so that you can also create contexts with any IServices/IPrincipal combo.
  • [ORM] sec changes - split auth, public endpoints, simplified principals
  • [SQL] Bugfix: If an entity E had columns named A and A1, a batch of statements which inserted multiple Es would generate invalid SQL, reusing the variable name A1. A simpler and faster variable naming scheme is now used.
  • [WPF] The.WPF IServices now creates contexts with the logged-in principal (similar to the pre-176.0 behaviour).
  • [WPF] Registering 'override sources' (assemblies containing extra controllers) is now part of RegisterControllerFactory().
  • [WPF] Added The.WPF.Composition.Options, and Builder.Configure(), replacing the various .WithFoo() methods.
  • [WPF] Expanded the LoginManager api to include explicit login/out methods, and added Options.AutomaticLogin - if disabled, the application will start logged-out. This can be used to implement username/password screens, user-switching or other forms of login management.
  • [WPF] SearchDelayMilliseconds is now configurable in Options.

v177.0.1

  • Fixed interpackage deps, which had been pinned down to 173.2.1 due to a packaging bug.
  • The.Extension is now uploaded to MyGet on release.

v177.0.0

  • This release requires an extension update.. in order to implement a change which will lead to requiring fewer extension updates in the future.
  • [MODEL] The framework version referenced by your project (rather than the extension version installed in Visual Studio) now controls the C# and VB type names of each attribute type.
  • [ORM] Fixed a case where PreferenceManager would not load preferences in time to read a value.
  • [ORM] Fixed NullReferenceException in PropertyPath.
  • [WPF] Surfaces now have a principal; on logout, existing surfaces are closed. The Principal property available to subclasses of screens, wizards, fields etc is the principal of their surface.
  • [WPF] Non-surface UI elements (ISidebarController, IMenuBuilder) are passed a principal on calls to initialisation and reinitialisation.

v176.0.0

  • [ORM] Rationalised context/principal creation methods. SecurityManager now has CreatePrincipal(), CreateAuthenticatedPrincipal(), CreateUnauthenticatedPrincipal(); IServices just has a single CreateContext() method which takes an optional IPrincipal.
  • [ORM] Removed CurrentPrincipal and ResetSession - these concepts are now UI-specific and the ORM is closer to stateless.
  • [ORM] PreferenceManager now manages the lifecycle of IPreferenceStore for stores which need to sync their data to a backend. The new Reload() api will force all the prefs to be refreshed. For now this makes the interface slightly more complicated, but we might make it simpler later by removing the responsibility for reading individual values from each store.
  • [ORM] AppDataPreferenceStore now has a public constructor instead of a static Create() method.
  • [ORM] Bugfix: DataContractEntityStore's constructor would sometimes incorrectly throw an exception when the model contained a non-legacy entity related to a legacy entity.
  • [WPF] Custom commands can now be added to all (or some) SearchControllers in an application by creating a SearchBehaviour and adding it to SearchOptions.
  • [WPF] IShell implementations no longer have to provide an InitComplete task.
  • [WPF] Added a new service, LoginManager, which replaces ShellInitComplete and the stateful functions from SecurityManager.
  • [WPF] Shell SplashScreens get early access to the LoginManager, which they can use to determine/present information about the startup process.

v175.4.0

  • [ORM] Bugfix: TypedPrefixSet<T>.GetPage could raise an ArgumentException if the set had previously been fully enumerated and GetPage's arguments referred to a range that extended beyond the set.
  • [WPF] SectionedCollectionFieldBase no longer has properties related to adding and removing items - these are handled by subclasses instead.
  • [WPF] Bugfix: LookupSectionedCollectionField was incorrectly not automatically adding entities selected in its selector to the collection.
  • [WPF] ZomboBox will no longer select only the first result when it loses focus without a dropdown box selection and forbids custom text. It will now select the first item with text that contains the string the user entered, or if no such item exists, the first item.
  • [WPF] The creation of individual criteria can now be overridden in criteria factories - override the Create[Foo]Criterion() method.

v175.3.1

  • [ORM] More information will now be included in the error message generated when a Currency or Decimal attribute value is outside the valid range, including the range itself and the length and precision property values that the range was calculated from.
  • [SQL] Bugfix: BufferedReader would incorrectly raise a NullReferenceException when executing ThawFrozenQuery.

v175.3.0

  • The.Framework no longer depends on System.Configuration.ConfigurationManager.
  • [LOGGING] Moved AddAppConfig() from The.Framework() to The.WPF().
  • [SEC] DBKeyProvider for PKIAuthentication now works on .NET Core, using new extensions FromXmlStringCore()/ToXmlStringCore().

v175.2.1

  • [WPF] Improved ZomboBox tooltips.

v175.2.0

  • This release requires an extension update.
  • release.bat is now gated on passing tests.
  • [MODEL] Entities' name and caption pluralisation can now be overridden; this supports homonyms and cases where different plurals are used in different contexts (e.g. indexes vs indices).
  • [WPF] Fixed some NullReferenceExceptions in ZomboBox and EntitySelector.

v175.1.0

  • [MODEL] Bugfix: 'genus' is now correctly considered singular (and pluralises to 'genera').

  • [WPF] ZomboBox improvements:

    • dropdown is no longer opened when a selection is already present
    • selection on focus loss has been refined
    • the control is now themeable in its own right and doesn't pick up TextBox themes
    • keyboard and mouse preselection no longer battle - the mouse uses a separate "prepreselection" which has no effect unless you click
    • LIRFs no longer limit the count for reference data
    • long suggestion entries now have a tooltip to display their full text
    • added IsTextChanged property, which can be used by fields to determine whether the user has actually entered anything for filtering purposes
    • when selecting reference data, no filtering is applied when text is not changed
    • content can now be added inside a ZomboBox, which will contribute to its dropdown's width (inline buttons and the like).
  • [WPF] A "Close All Tabs" tab context menu item has been added.

  • [WPF] Bugfix: Criteria with defaults caused search screens to be loaded twice.

v175.0.0

  • Updated Xunit for some nice perf improvements. Running the full test suite is back down under 40 seconds for now.
  • [MODEL] Serialise's ReadFileAs, ReadBytesAs, and ReadStreamAs methods were untested and unused and have been removed.
  • [MODEL] Serialise's remaining methods should no longer raise first-chance FileNotFoundExceptions.
  • [WPF] RecentItemsController should also no longer raise first-chance FileNotFoundExceptions.
  • [WPF] SuggestionBox and EntitySelector have been replaced by the new ZomboBox control. It's a simpler and more welcoming version of ComboBox.
  • [WPF] InlineReferenceFieldBase and LookupSectionedCollectionField use the new EntitySelectorModel/View to ensure that their use of ZomboBox is consistent.
  • [WPF] SuggestionField has also been updated to use ZomboBox.

v174.2.0

  • [ORM] The ILoggerFactory implementation built into the framework didn't implement either the M.E.L. 1.0 idiom of using "Default" as a fallback pseudo-category or SetMinimumLevel() to achieve the same thing. Now it supports both.

  • [ORM] New method ILoggerFactoryBuilder.AddAppConfig() - this is like the .AddConfiguration() which already exists for applications using M.E.C.; it works analogously, treating app.config appSettings as key paths, the same way you use them in environment variables. For example, the following appsettings.json:

    {
      "Logging": {
      	"LogLevel": {
        "Default": "Warning"
      },
      "Debug": {
        "LogLevel": {
      	"The.Persistence": "Information"
        }
      }
      }
    }
    

    is equivalent to the following app.config:

      <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <appSettings>
      	<add key="Logging:LogLevel:Default" value="Warning" />
      	<add key="Logging:Debug:LogLevel:The.Persistence" value="Information" />
        </appSettings>
      </configuration>
    

    Verbose, but consistent.

v174.1.0

  • [ORM] Clone() now has an optimisation for the trivial case where an entity is already in the right context - this makes some higher level code easier to write.
  • [ORM] WebEndpoint now configures its http/tcp stack more appropriately; persistence ops now generally take 1 roundtrip instead of 3.
  • [ORM] More query types can now be batched - SelectByFrozenQuery, SelectByType, SelectByQuery, ThawFrozenQuery.
  • [ORM] created/modifiedBy/On are now implemented in the core framework rather than the responsibility of each store. This improves performance (1 less roundtrip per SQL batch) and it means that the values are available in memory after a save.
  • [WPF] The 'lookup context' used as an optimisation on Content screens is now accessible from owners of embedded content controllers and can be specified (in order to use a shared cache) in ContentOptions.

v174.0.0

  • R.I.P. The.Utility.nupkg; when I created it I was about to move some shared code from The.Reports but changed my mind. Those types are back in The.Model.nupkg for now.
  • [ORM] Licensing is now better about searching for the files it needs at default paths and in resources. In particular, model-hash licensing now supports loading its model file from a resource as well as from a file. You can help it along even further by explicitly specifying an entry-point assembly when Build()ing a composition root.

v173.2.0

  • [ORM] RemoteEntityStore now handles principal-switches when using encrypted sessions, establishing a session for the new identity.
  • [WPF] When not using a splash screen, TabbedShell now shows its window ASAP for responsiveness.
  • [WPF] Shell: errors handling security-principal updates no longer take down the application.
  • [WPF] Shell: Global notification bar is now in a less terrible location.
  • [WPF] Shell: Application loading is now more responsive when waiting for slow database connections.
  • [WPF] Bugfix: On Windows 7, opening a new tab was creating an error notification due to a bug in a decorative event handler.

v173.1.2

  • [WPF] Shell: selected tab headers now take on the same brush as the tab area.

v173.1.1

  • [WPF] The shell no longer stacks Success-severity notifications - new notifications of any severity will dismiss existing successes. Info, Warn and Error messages remain and stack.

v173.1.0

  • [WPF] ContentModels now have FindField() and FindSection() methods.
  • [WPF] ContentModel dynamic binding now works for decorated fields.
  • [WPF] AsyncShellCommand has been added.
  • [WPF] Bugfix: The fields in the main section of any content screen were incorrectly being created and databound twice, which led to strange interactions in some cases.
  • [WPF] Bugfix: When screen creation failed, errors were shown on the wrong thread, creating a dispatcher-violation error which hid the true problem.

v173.0.0

  • This release requires an extension update.

  • Renamed The.Utility to The.Tool and removed its "keygen" option - we are not using this anymore, we use "license" to sign licenses with a pre-generated keypair.

  • Extracted miscellaneous useful types, mostly from the The.Utility namespaces in The.Model and The.Framework, so that they can be reused in other places like The.Reports.

  • Simplified the build some more - several projects now single-target .NET Standard instead of multi-targeting .NET Framework and .NET Core.

  • [MODEL] Bugfix: There were some inconsistencies between the model editor and snapshots when it came to generating relationship names and captions.

  • [MODEL] Overriding the name or caption of one side of a relationship will now be reflected in the default name or caption of the other side, if there are multiple relationships between the two entities.

  • [MODEL] Bugfix: Errors would incorrectly be raised in the editor in the following cases:

    • A user created an attribute, modified it, and then deleted it
    • A user created a relationship and then deleted it
    • A user created a new attribute, moved it, then deleted another attribute, then created a relationship, then moved the relationship, all in the same section
  • [MODEL] Bugfix: When editing models with non-empty Empty Text values, the optimiser would incorrectly fail to optimise away the first event from a redundant series.

  • [MODEL] Bugfix: ChangeEntity events would incorrectly always blank out the DiagramNumbers property.

  • [MODEL] Bugfix: Spaces in section names were incorrectly considered invalid in the editor.

  • [MODEL] Attributes and relationships can now be created from a section view or context menu in the editor.

  • [MODEL] Any editor command that creates a new node will now also immediately select that node.

  • [MODEL] Bugfix: The section/property listing in entity detail was incorrectly not displaying properties when the "Include sections" option was off.

  • [MODEL] Bugfix: The editor would sometimes crash completely when attempting to notify the user of an error.

  • [MODEL] Bugfix: Trying to move the last property out of a section would fail with an error.

  • [MODEL] Bugfix: The editor would sometimes fail to keep entities in alphabetical order when interpreting an event that changed an entity's name.

  • [MODEL] Bugfix: New attributes would incorrectly appear to be added before all other properties in the section.

  • [ORM] The.Framework no longer depends on System.Dynamic or uses the DLR, improving compatibility with AOT environments.

  • [ORM] The.Framework no longer depends on System.Drawing either; image thumbnailing has been moved to The.WPF.

  • [ORM] Updated to Microsoft.Extensions.Logging.Abstractions 2, which has built-in filtering and better runtime configuration mechanisms. Using framework logging is now simpler: The.Composition.Builder now has a WithLogging() method, which operates on an ILoggerFactoryBuilder similar to the ILoggingBuilder in ASP.NET Core. You don't need to register a LoggerFactory explicitly, and can eschew the Microsoft.Extensions.Logging package. It's still possible to call RegisterLoggerFactory() to replace the built-in factory - in order to integrate with ASP.NET Core, for example.

  • [ORM] Renamed The.Licensing.Status to The.Licensing.CheckResult to avoid confusion with The.Utility.Status.

  • [ORM] The.Security.NTLMAuthentication is now available on .NET Core, as long as you're running on Windows.

  • [ORM] PasswordAuthentication now supports remote logon without direct DB access. The server has a password-derived key which it uses as a shared secret in order to encrypt an AES session key; the client decrypts the new key using RFC2898.

  • [ORM] Added Traits.Time to format/parse framework Time values as time-of-day instead of duration.

  • [UTILITY] Moved Optional to The.Utility (from The.Model).

  • [WEB] The.Web now supports (and requires) ASP.NET Core 2.

  • [WEB] IServiceCollection.AddTheFramework() now requires a builder or a function, not an IServices instance, so that the framework can integrate more deeply into ASP.NET (lifetimes, logging, eventually authentication).

  • [WPF] Removed several tabstops from TabbedShell sidebar area.

  • [WPF] Bugfix: DisplayController.LoadEntity would try to load counts for related transient entity types.

  • [WPF] Added StringToTimeConverter, which applies the Time trait's microformat.

  • [WPF] Time and DateTime fields now use the Time trait.

v172.1.0

  • [ORM] Decimal normalisation will now also ensure that the input value is within the length limits of the attribute, throwing an exception otherwise.

  • [WPF] It's now possible to override some shell resources without setting all of them in an application. Adding something like this to your app resource dictionary will do it:

      <BitmapImage x:Key="{x:Static shell:Resources.LogoImageKey}" UriSource="mylogo.png"/>
    

    Previously this required also setting the lightbox dimensions, window minimum size, etc.

  • [WPF] Added new shell resource key SurfaceBorderBrushKey - this controls the brush used to separate screen areas such as the menu, sidebar, tab area, etc.

  • [WPF] MultiCommandButton, used in drop down menus, should now be more easily styleable - previously its content was nontextual and hard to affect reliably.

  • [WPF] Added IScreenCommand.Executing and Executed, events which fire before/after a screen command runs. This is intended for UI code which wants to provide feedback on commands and so on.

v172.0.3

  • [WPF] Criteria controller overrides can/must now specify CriteriaOptions in their constructor signatures.

v172.0.2

  • Fixed a missing DLL in The.Extension.

v172.0.1

  • [WPF] Fixed generated criteria template for the case of non-nullable adminonly attributes.

v172.0.0

  • Improved test.bat/release.bat. You no longer have to build in the opposite config before running them, and they don't mess with PATH anymore.

  • [ORM] The.Framework has been ported to .NET Standard 2.0. All persistence and security components should now work cross-platform, with two exceptions: Windows authentication and GDI image thumbnailing.

  • [ORM] Added The.Utility.CSVReader, inevitably.

  • [SQL] The.SQLServer has been ported to .NET Standard 2.0. For native platform support it relies on System.Data.SqlClient - I'm not sure whether this works in Xamarin but it definitely supports .NET Core.

  • [TEST] The.Xunit has been ported to .NET Standard 2.0. It no longer depends on other The. packages - it's just standalone testing utilities ([ContractTheory], [Skippable], [STAFact], NominalOrderer, etc).

  • [TEST] The.WPF now contains namespace The.WPF.Mocks with some useful types for testing.

  • [WEB] The.Web has been ported to .NET Standard 2.0. For now, ASP.NET Core itself only supports .NET Framework and .NET Core (not Xamarin or UWP).

  • [WEB] ASP.NET Core 1.1 apps referencing The.Web now contain workarounds allowing them to build on .NET SDK 2.0 and run on .NET Core 2.0.

  • [WPF] Added SearchOptions.CanCreate, which can be used to prevent the Create command from showing up on search screens.

  • [WPF] Added CriteriaOptions.AdminMode, which joins the existing ListOptions.AdminMode and ContentOptions.AdminMode values. The 'AdminOnly' model option is now comprehensively implemented; what it does is add an extra check which prevents properties from displaying in various places unless

    a) the AdminMode option is set when creating a screen. and
    b) the user actually is an admin (IPrincipal.CheckAdmin() == true).
    

    This can be used to implement application-specific semantics (for example, GET$ is using 'admin users' in the sense of administrators or secretaries). We'll probably also add something like a context menu option to "go into admin mode" on Search and Display screens, allowing admin users in the security sense to see 'internal' application data.

  • [WPF] Exposed SearchController.Metadata to subclasses (the current screen's entity's IEntityInfo).

v171.4.0

  • The.Model and The.Reports now support .NET Standard 2.0 (up from 1.4/1.5 respectively). This is narrower platform support than before, but it gets us a few benefits:

    • The.Model.Generator has been removed and its functionality incorporated back into The.Model.
    • Fixed The.Reports runtime failures on .NET Core 2.0. It worked on 1.0 but backwards compatibility wasn't perfect.
    • Both packages now single-target a netstandard tfm only, reducing build times and cutting down their dep graph to just netstandard.dll itself.
  • [ORM] EntityReferenceProperty.IsDefaulted is now correctly cleared when the reference is updated remotely or generically.

  • [SEC] Added PasswordAuthentication, an authenticator which supports direct login or remote key exchange using a username and (hashed+salted) password.

  • [SEC] Added ProfileAuthorisation, a simple authoriser which determines whether a user is an admin or not using their IUserProfile.

  • [WPF] IShell.InitComplete now waits for the menubar and sidebars to load before signalling.

  • [WPF] Bugfix: Boolean fields would not show the correct default value of a boolean field, if its default value were set to True.

  • [WPF] CreateController now has GetCustomCommands();

v171.3.1

  • [WPF] Sidebars and tab headers now scale with the rest of the UI.

v171.3.0

  • [ORM] Added PreferenceManager.Flush() to explicitly save preferences (they're already saved on shutdown and on a timer).

v171.2.1

  • [WPF] RecentItemsController is now user-aware (or rather, it follows sidebar best-practice of reinitialising every time it is Attached).

v171.2.0

  • [ORM] SecurityManager.ResetSession() was originally designed for impersonation - it now also works for the "switch user entirely" case.

  • [ORM] Authorisation can now be reentrant in scopes (that is: IAuthorisation implementations can safely use IEntityContext to look up authz info from a DB).

  • [ORM] ProfilePreferenceStore is now user-aware and will invalidate its preference cache when you switch.

  • [WPF] Improved consistency of screen command overrides:

    * SearchController no longer adds "Create" as a 'custom' command, so overriding GetCustomCommands() doesn't inexplicably replace it
    * DisplayController now also has GetCustomCommands()
    * All the command methods on SearchController and DisplayController are now overridable
    
  • [WPF] Shell more reliably shows current user at login.

  • [WPF] Inky theme now styles password boxes.

  • [WPF] Added error handling for sidebar de/registration.

  • [WPF] TabbedShell now supports shobiz-style reinit of control surfaces (menu buttons, sidebars, statusbar) on user switching.

v171.1.0

  • [WPF] Improved consistency of screen command overrides:

    * SearchController no longer adds "Create" as a 'custom' command, so overriding GetCustomCommands() doesn't inexplicably replace it
    * DisplayController now also has GetCustomCommands()
    * All the command methods on SearchController and DisplayController are now overridable
    

v171.0.1

  • [ORM] Fixed a breaking change in IPrincipal which had been temporarily necessitated by an obfuscator bug.
  • [ORM] The three use cases of IAuthentication (get-identity, sign-data, encrypt-data) are now consistently split into "client" and "server" functions. Only the server-side parts require an IEntityContext, and only the client-side parts are expected to have a 'current" ambient identity.

v171.0.0

  • Building TheFramework.sln now requires Visual Studio 2017 15.3.
  • [ORM] Dependency-based automatic property recalculation has been added, adapted from the system in NPS. To have a property automatically recalculated when its dependencies change, apply the [CalculationDependency] attribute to its calculation method and then call the AddCalculationDependencyHandlers method on its parent entity. The disposable returned should be disposed of when automatic recalculation is no longer needed.
  • [ORM] PropertyPath is now backed by a persistent linked list structure, which matches its usage and should drastically reduce allocations during use.
  • [ORM] The.ChangeTracking namespace now contains two top-level APIs - ChangeDescription and ChangeNotification. A lot of their functions used to be available ad-hoc on entities and properties.
  • [ORM] FeatureManager now provides safer IUserProfile access through a serialised modification function
  • [ORM] Fixed "Post-GOCKP kernel is Loaded instead of Creating".
  • [SQL] All write operations are now batched. This is a large performance improvement for big saves and property recalculation - over a 20x speedup in some scenarios. The maximumBatchedInsertCount parameter of SQLEntityStore is now maximumBatchedQueryCount and applies to the whole sequence of write operations.
  • [WEB] 'Scoped' contexts have been reduced in scope a little. They still bypass licensing and authorisation, but no longer bypass authentication. IAuthentication.GetIdentity no longer receives a context at all - authenticators are expected to have some out-of-band method of determining their Identity. This change makes scoped contexts, and therefore features like ProfilePreferenceStore, work via RemoteEntityStore.
  • [WEB] Removed operation-batch copies from the RemoteEntityStore hot path.
  • [WEB] Fixed a race condition allowing clients to force servers into accepting unencrypted messages.
  • [WPF] Added better error boundaries around login, which improves the quality of error messages.
  • [WPF] Bugfix: MultiCommandButton incorrectly had black text when disabled.

v170.1.0

  • [ORM] Bugfix: SecurityManager.CurrentPrincipal used sync-over-async and was vulnerable to deadlock when used with true-async like SQLEntityStore. It now applies the relevant workarounds (delegation to the threadpool).
  • [WPF] Changes to list column widths are now stored in user preferences.
  • [WPF] Bugfix: TabbedShell didn't respect SplashResult.AppShouldExit.

v170.0.0

  • [ORM] IServices.CreateLogger<T>() now returns an ILogger<T> instead of the nongeneric ILogger.

  • [ORM] Bugfix: Recalculator would skip calculating for the second-last page of each entity type.

  • [ORM] Bugfix: The defaultedness of reference properties is now cloned, fixing validation error displays.

  • [WEB] The.Web provided several IApplicationBuilder.UseThe___() methods to add MVC controllers in pipeline forks, which was convenient but not flexible. Instead, it now supplies controller base classes which can be subclassed. They run in the application's main MVC middleware instance, and can be overridden to add app-specific routing, authorisation, action filters, etc.

    More concretely: to use the persistence proxy, subclass ProxyControllerBase and use UseMVC() instead of UseTheProxy(). To use the SPA API, subclass SPAControllerBase and use UseMVC() instead of UseTheSPA(). AddTheFramework()/AddTheProxy()/AddTheSPA() calls are still required in ConfigureServices.

  • [WPF] TabbedShell's global surface now supports SetContent and the full set of ISurface methods - any screen displayed on the global surface will be shown when no tabs are open.

  • [WPF] FastTabControl's TabPanel header can now be styled. TabbedShell uses this to line things up better when not actually displaying any tabs.

  • [WPF] The textbox-like part of a CollectionSelector will now execute the control's SelectCommand when clicked.

  • [WPF] FieldControl's default style no longer sets its MinContentWidth.

  • [WPF] The Inky theme no longer sets MinWidth for TextBox and EntitySelector.

v169.0.1

  • [WPF] Validation errors which start with "Warning: " are displayed with a less vivid border. This is just a visual hack, but will hopefully lead to an actual noncritical-warning system at some point.
  • [WPF] Bugfix: TabbedModel.MenuVisibility could nullref at startup.

v169.0.0

  • [MODEL] The.Extension can now discover theModel files and template outputs at the top level of Foo.Model projects without a Model/ or GenOnly/ subdirectory.
  • [MODEL] Templates which use the ##Replace#Foo directive, if discovering multiple files named Foo, now replace the contents of the one nearest to the model file instead of the first alphabetically. This is a step towards supporting multiple models in a single solution.
  • [MODEL] Fixed an extension crash when running Generate Code with model-containing projects unloaded.
  • [OFFICE] ExcelSpreadsheet now supports adding and removing worksheets, resizing columns, applying some style changes to cells, and merging cells.
  • [SEC] The IUserAccount synthesised entity is now IUserProfile - this is the entity which it's safe for users to write to. IUserClaim is the one with security information in it.
  • [SEC] FeatureManager.GetUserProfile now lets you look up the profile for a specific identity, not the identity attached to the context you use for the lookup.
  • [SEC] Added ProfilePreferenceStore, an IPreferenceStore which saves preferences in the userprofile entity.
  • [UTILITY] Added a new ILoggerProvider, ProgressProvider - this writes logs to an IProgress<Status>.
  • [WPF] Enhanced splash screens - the delegate can now return readiness or failure, and if it throws an exception the error will be handled reasonably.
  • [WPF] SearchModalController now provides an override point for creating its SearchController.
  • [WPF] The Progress screen's log view now autoscrolls, and its progress messages go away more visibly when progress is complete.
  • [WPF] TabbedShell now collapses the menubar if your menu builder doesn't provide any buttons/groups.
  • [WPF] Removed a bunch of needless value conversions (like Convert<int, int>()) generated by FieldFactory.
  • [WPF] Validation fixes for dates, datetimes and texts (multiline).
  • [WPF] Bugfix: Model-side changes to ValueField would not trigger a view update.
  • [WPF] Bugfix: View-side changes that made ValueField invalid would not appear to take effect.

v168.0.0

  • This release is focused on performance for applications with a high cost of persistence - cloud DBs, http proxies, encrypted operations, etc.
  • [ORM] Improved layering in The.Persistence: PersistenceManager now has a much smaller API, with higher-level convenience methods (like GetByID) built on top of it as extension methods. Like other managers, it now represents the 'public api' boundary - applications can write this kind of method also, using persistence ops in more flexible ways. PersistenceManager's Read and Write methods basically just provide secured and error-checked access to the entity store for a specific model.
  • [ORM] Some types of read operations can now be batched like write operations. Batched operations are sent in a single call through proxies, and can potentially be fused into a smaller number of calls by the actual database-backed store. IEntityStore.ExecuteReads<T>() has been split into ExecuteRead<T>() and ExecuteReads(); the non-generic method executes a batch, and the existing set of ops has been divided into GenericReadOperation<T> and BatchedReadOperation hierarchies. The following operations are eligible for batching so far: GetByID, SelectByRelationship, CountByQuery.
  • [ORM] RemoteEntityStore envelopes batched operations in a single encryption call.
  • [ORM] Reduced CPU overhead of symmetric encryption in RemoteEntityStore.
  • [ORM] RemoteEntityStore was signing write operations even when not requested. This reduced performance of saves (and startup) by doing extra work.
  • [ORM] Added a fast path for count queries which doesn't require dynamic query translation to an unknown type.
  • [ORM] TypePrefixSet can now be created with a known count rather than lazily loading its count like GetAll does.
  • [ORM] Added an overload of CreatePreauthenticatedContext which allows reuse of an existing principal.
  • [SQL] SQLEntityStore uses MARS to execute batched read ops in a single database call.
  • [SQL] Indexes will now be generated for all legacy-only relationships. These indexes are nonunique regardless of relationship multiplicity, so they shouldn't constrain the table data in any way.
  • [WEB] WebEndpoint sends batched operations in a single POST.
  • [WEB] The AddProxyServer() extension method now lets you configure session duration (default: 5 minutes).
  • [WEB] Automatic session renewal is now working, preestablishing a new session within a configurable threshhold of expiry (default: 30 seconds).
  • [WPF] List screens use batched queries to load relationship columns at a cost of one call per page instead of one per column.
  • [WPF] Display screens use batched queries to load choices sets for edit controls. The loading can be customised to do your own batching with an override.
  • [WPF] Reminders sidebars use batched queries to count available tasks periodically/on save.
  • [WPF] VirtualisedSet now preloads a page of data for smoother scrolling.
  • [WPF] EntitySelector now handles errors when trying to load its choices (which may be user-supplied code, or a database connection error).
  • [WPF] Added a non generic WizardBase with no result type.
  • [WPF] TabbedShell now supports a "splash screen", a function which will be awaited by the shell before showing its main window.

v167.0.0

  • [ORM] IEntityStore now has an ConnectAsync method which checks that the store is responding, providing reasonably comprehensive diagnostics when a server is unreachable or the client is not authenticated.
  • [ORM] SecurityManager uses ConnectAsync to validate that there is no remote authentication failure when creating an IPrincipal.
  • [ORM] Added remoting support for the ThawFrozenQuery read operation.
  • [ORM] RemoteEntityStore uses the IEndpoint equivalent of ConnectAsync to establish a session, either explicitly when Connect is called or implicitly on read or write with no session present. This lazy session creation is mainly for edge case handling - the normal depdendency chain is "persistence ops" <- "entity context" <- "principal" in which case the security subsystem will have established a session.
  • [ORM] RemoteEntityStore and UseProxyServer() now take an AuthenticationProtocol enum. AuthenticationProtocol.VerifiedOperations is the original per-operation signing mode; EncryptedSession or VerifiedOperationsAndEncryptedSession use a symmetric key (initially exchanged via public-key). This is higher performance when using a physical RSA token, and potentially gives us double encryption.
  • [ORM] Various security bugfixes and error andling
  • [ORM] Bugfix: Box<T> would not raise ValueChanged if its value changed during a call to SetDefaulted.
  • [SQL] SQLEntityStore is now aware of more SqlException number codes.
  • [SQL] Bugfix: CountedDatabase was not passing through the inner IDatabase's Name property correctly.
  • [WPF] Bugfix: Transient relationships were incorrectly included in the columns available to sort by in the Manage Columns dialogue box.
  • [WPF] Bugfix: MultibarController incorrectly did not begin expanded when an inner sidebar attempted to expand in its OnAdded method.
  • [WPF] Reminders that throw an exception during a refresh now log that exception rather than showing it as a notification on the global surface.
  • [WPF] TabSurface.ShowNotification will now fail fast if called from a thread other than the dispatcher's.
  • [WPF] Added IServices.ShellInitComplete, an awaitable task which does what it sounds like.
  • [WPF] Minimum window size is now very small.

v166.1.0

  • [ORM] PrimitiveAttributeBase.IsDefaulted has been moved to AttributeBase.
  • [ORM] Cloning an entity now copies the defaultedness of its attributes as well as their values.

v166.0.2

  • [SEC] SecurityManager's new ResetSession method allows the current session to be ended immediately.

v166.0.0

  • [SEC] DBKeyProvider now caches the result of public key lookups, saving a number of internal sql queries per persistence op.
  • [SEC] Improved error reporting and logging.
  • [SEC] Improved authentication performance - creating contexts and acquiring principals now only incurs an I/O cost once per session.
  • [WPF] The Reminders sidebar now executes queries in parallel by default, and performs its updates on the threadpool instead of the dispatcher for responsiveness.
  • [WPF] The simplification of FieldFactory continues - CreateInlineCollection is removed in favour of just instantiating *InlineCollectionField.
  • [WPF] Lookup fields in editable lists now use a common context (allowing caching).

v165.0.0

  • [MODEL] Several 'invalid event' error messages have been improved.
  • [MODEL] Import structure customisation now supports setting a custom section name for an attribute.
  • [ORM] IAuthentication now supports the concept of failing to authenticate or to verify, with an error message instead of some implementations unpredictably throwing. SecurityManager raises an event when a context acquires an authentication state, and this information is plumbed through from remote servers back up to the client and the shell. Applications can check IPrincipal.IsAuthenticated to see whether a principal is usable - unauthenticated principals will fail all tests, so they can't read/write the entity store.
  • [ORM] Added The.Security.PKI.PKIAuthentication, originally from Marvin. This implementation supports remote authentication using a private key available to the client and a public key known to the server. It comes with CSPKeyProvider for signing using a USB token or 'smartcard" and DBKeyProvider for verifying using keys stored in the user-claims model feature.
  • [ORM] Added IUserAccount.LastLogon.
  • [SQL] SQLImportSource has been added.
  • [WPF] TabbedShell now monitors authentications and displays the user's "current" logged-in state as of last context creation.
  • [WPF] If the User Accounts feature is enabled, TabbedShell now looks up or creates an account when a user authenticates. It uses the DisplayName in place of Identity.Name, and updates LastLogon.

v164.0.1

  • [ORM] IValues now have a concept of being in 'default state'. They can be SetDefaulted() and checked for IsDefaulted. This is totally orthogonal to HasChanges() - something can be defaulted or not regardless of whether it's been altered. In the case of attribute and reference values, properties on an IsNew entity will be IsDefaulted unless/until they receive a value through the .Value property, regardless of whether that received value is the default; otherwise, they'll be IsDefaulted only when explicitly cleared/SetDefaulted.
  • [ORM] Lenses now have a 'default defaultedness' as well as a default changedness - you can create them with only a getter and a setter if you want the same notions of initialValue-based tracking as Box.
  • [ORM] Persistence logging now provides detailed identity/op/args information for analytics.
  • [ORM] Fixed the serialisation of result metadata, carrying security status and autonum/retry info through JSON/XML.
  • [ORM] Box<T> and other IValues now support MarkUnchanged() like entity properties.
  • [SQL] The.SQLServer now supports using reserved words as attribute names.
  • [SQL] Bugfix: Enabling transactional reads now actually works.
  • [WPF] Defaulted values are now presented by ValueField as an 'empty' state regardless of their actual value. For example, an int attribute with a default of 0 or 1 will be shown as an empty textbox on a Create screen. Conversely, clearing that textbox on a Display screen will show as empty but reset to default rather than null.
  • [WPF] Requiredness now has a more intuitive impact on validation - the generated rule is that IsRequired attributes and references must not be IsDefaulted. Nullability no longer has a direct relationship to requiredness - it only influences the default value (if no explicit default is set in the model).
  • [WPF] Fixed change descriptions not showing on close due to binding errors.
  • [WPF] The MultilineTextBox control (used by Text fields) now has a tabstop.
  • [WPF] Greatly improved tabs/keyboardability of complex display screens.
  • [WPF] All lookup fields on a screen now share a common "LookupContext", which is also available to subclasses, for their dropdowns and searches. This prevents unnecessarily looking up the same reference data many times.

v164.0.0

  • [ORM] RemoteEntityStore now supports either XML or JSON, and serialised persistence operations have been reduced in size. A complex query which was previously 6.1KB is now down to about 2.8KB in json, or 3.6KB in xml (both are around 700B gzipped).
  • [ORM] Read-side security errors are now passed through persistence intact, including remote security errors on a server, and presented/logged more helpfully rather than as a "read failure".
  • [ORM] IAuthentication is now lower level- it works with names and blobs. The higher level SecurityManager code handles more of the boilerplate around identity objects, simplifying individual authentication implementations.
  • [ORM] New feature: User tables. This model feature synthesises a user account and user claim table, which can be used to store arbitrary data about some identity. PKI authentication will use it to store enrolled users' public keys for signature verification.
  • [ORM] New service: FeatureManager, which gives access to the synthesised feature types through interfaces IAuditLog, IUserAccount, IUserClaim.
  • [ORM] New licensing mode: model-prefix hashing, which verifies an application model + some leeway to change it. This is for cases where we don't build the software and so can't sign specific binary builds.
  • [SQL] SQLEntityStore has a new config option, bool transactionalReads - if this is set to true, read operations will take place in linearizable transactions (write operations are always transactional). Using transactional reads reduces performance, but also prevents race conditions if you want to rapidly read your own writes.
  • [WPF] TabbedShell can now handle startup errors in user-supplied delegates and app plugins using the usual notification mechanisms (ISurface notifications, ILogger reporting). The shell now uses multiple background tasks to prioritise getting as much UI onto the screen as possible when some individual component is slow - e.g. license checking of a model hash, persistence over HTTP, user-written loops in menu-building. You can await the new IShell.InitComplete property to be able to run some code after all shell elements have loaded.
  • [WPF] Notifications now stack vertically rather than new notifications displacing the old.
  • [WPF] ISurface has a new Window property which returns the WPF window on which the surface is being presented. This can be useful to obtain GDI handles or lock modal windows to the right parent.
  • [WPF] Bugfix: SearchController could throw unhandled ReadFailureExceptions when handling EntitySaved.
  • [WPF] Bugfix: TabbedShell would sometimes try and show notifications on its GlobalSurface from a background thread, breaking dispatcher assumptions.
  • [WPF] Bugfix: ListController would sometimes try and show notifications from a background thread.

v163.0.0

  • The Extension now has a simplified build with a bunch of legacy removed. It no longer includes item templates, but various gen-time bugs are fixed and it should be much more maintainable now.
  • T4 compilation was apparently-functional but in reality quite broken. Now it is less broken. In the long term we may have to switch to a new codegen solution, it really doesn't understand msbuild 15 at all.
  • Worked around a packaging bug in The.Web which could cause compile errors by treating typescript declaration files as source.
  • All SDK projects are built using a common.props file. Advantages include uniform obfuscation (for example, The.Xunit could not be obfuscated previously).
  • All NuGet projects now use the new SDK. They can be packed without using batch files, from visual studio (rightclick->Pack) or the commandline (msbuild /t:pack); TeamCity is also now capable of packaging and producing releases. Versioning is controlled using the common.props file and msbuild properties internally. However, test.bat and release.bat should still work like before.
  • [MODEL] The previously SQL-specific AuditLog feature has been turned into a synthesised-model feature and reimplemented for all backends. Audit logs can be accessed as entities through the IAuditLog interface or FeatureManager class.
  • [ORM] Licenses can now be either test-only or production-licensed for a specific licensee. New test licenses are required by The.Utility to have an expiry date, although all existing licenses are also considered test-only.
  • [SQL] Query translation now supports interfaces other than IEntity - you can use any interface an entity has as long as you supply the metadata of a concrete entity type.
  • [SQL] Query translation now supports the two-argument forms of First(), FirstOrDefault(), Single() and SingleOrDefault().
  • [WPF] Breaking: EnumField and NullableEnumField are now ValueFields.
  • [WPF] ConversionManager now automatically supports conversion of enums to their underlying types and back.
  • [WPF] TabbedShell now displays licensing information in the status bar.

v162.1.0

  • [ORM] PresetAuthentication now supports remote security. This is just as non-secure as using preset authentication locally! Don't use it on a publicly exposed server!

v162.0.1

  • Fixed a packaging issue requiring apps to explicitly reference System.Net.Http when using WebEndpoint.
  • [ORM] WebEndpoint now supports un-rooted endpoints (as in http://someserver/some/path/prefix).
  • [WPF] Catch and report errors in menu-building code (previously, unhandled exceptions in some application's Menu.cs would lead to a crash).

v162.0.0

  • The Framework now supports the VS2017/MSBuild 15/".NET Core Take 2" SDK. The.Extension works in VS2017, and The.Web projects work with nu-csproj.
  • [MODEL] The.Model now supports netstandard1.4 (desktop, core, uwp and xamarin).
  • [MODEL] New package The.Model.Generator - this is the template runner functionality, desktop-specific (due to AppDomain isolation) but not necessary during runtime of a framework app.
  • [MODEL] Fixed colour theming for section lists.
  • [ORM] Use of ListSortDirection in entitysets has been replaced with SetOrderingDirection (we already had SetOrderingType).
  • [ORM] Removed third-party dependency Serialize.Linq - equivalent functionality now exists in the framework as 'surrogates', serializable copies of expression trees integrated into our own expression-rewrite system. This will give us control over performance and bugs of remote persistence rather than relying on a library which has since become unmaintained.
  • [WEB] Updated from ASP.NET Core 1.0 to 1.1. If the dependency change leads to any weird errors, try using <AutoGenerateBindingRedirects>True</AutoGenerateBindingRedirects> in your project file.

v161.0.0

  • [MODEL] Bugfix: VersionedObject serialisation was zero-padding data to >= 256 bytes.
  • [SQL] JoinTableSide now has separate Name and PropertyName fields. PropertyName gains the 'legacy' prefix for legacy-only properties, while Name stays the same.
  • [SQL] Bugfix: Querying an entity with an attribute named 'Return' would cause a SqlException.
  • [SQL] Frozen queries will now be stored in new tables named _Query and _QueryEntity instead of in a table per query. This removes the need for application users to have permission to create and drop tables.
  • [SQL] Breaking: Frozen query IDs are now of type long instead of strings.
  • [WPF] Bugfix: The modal resize grip would resize modals at half the rate the user would expect.

v160.3.0

  • The.Xunit is now using the released version of xunit 2.2.0, and is no longer itself a prerelease package.
  • [MODEL] The "Use as foreign key" command now respects the form/list visibility of the attribute in its created relationships.
  • [MODEL] DataContractEntityStore now supports case-insensitive string collation for queries. Insensitivity is on by default, but can be disabled with a constructor parameter.
  • [MODEL] Bugfix: Renaming empty sections was failing with an error.
  • [WPF] Textbox ValueFields now consciously preserve extra user whitespace, despite potential normalisation of underlying string attributes.

v160.2.3

  • [ORM] Bugfix: DCES shared stores being disposed would dispose shared locks.

v160.2.2

  • [WPF] MenuBuilder bugfixes.

v160.2.1

  • [WPF] MenuBuilder.Default now deals more gracefully with large amounts of non-reference-data entities by creating a submenu.

v160.2.0

  • [MODEL] Updated the data-transforming Copy events. There's a new one, CopyRelationship, and the previous events have had clarifying renames and semantic improvements. The 'convert to relationship' command now uses CopyRelationship to make the change importable.
  • [MODEL] Model version upgrades will now strip the old LegacyRefID tags which used to be used as a concordance with Model.xml files. They're taking up a lot of space, and we won't be interoperating with Model.xml any further.
  • [MODEL] Bugfix: The Copy Entity command was failing due to bad Precision handling.
  • [ORM] The import planner has been improved. It can now establish self-referential relationships (like Contact.NewVersion) and establish relationships from either modelled side - previously it was limited to LTR in support of the 'Extract foreign key' command. Import support has been added for the CopyRelationship event and multi-stage relationships generally.
  • [ORM] DataContractEntityStore can now be initialised with an existing DCES, sharing its data (and serialising to the same file, if any). This allows stores with different metadata, including legacy metadata, to operate on a live dataset.
  • [WPF] Bugfix: Modal screens could raise an InvalidOperationException if cancelled too late to stop their result from being generated.
  • [WPF] The Multibar sidebar will now automatically expand if one of its inner sidebars attempts to expand.
  • [WPF] Bugfix: Right-click->'Manage columns' allowed transient attributes to be selected for ordering, leading to an error.

v160.1.0

  • [MODEL] Added 'Add section' command to entities and a 'Delete section' command for empty sections.
  • [MODEL] Improved editor context menus.
  • [ORM] Attribute values are now normalised whenever a new value is set, including when reifying data from persistence.
  • [ORM] Decimal and nullable decimal attributes now normalise their value to ensure that it has no more precision than allowed by the model, and has the minimum precision required to represent that value (no trailing zeros after the decimal point).

v160.0.14

  • [WPF] Bugfix: Calling WizardController.NotifyValidityChanged would throw a NullReferenceException under certain conditions.

v160.0.13

  • [WPF] VirtualisedSet's indexer has been confirmed to sometimes be called incorrectly by WPF; this case is no longer considered an error.

v160.0.12

  • [WPF] Bugfix: The VirtualisedSet fix in v160.0.6 was insufficient - it incorrectly displayed a notification, and didn't include enough information in the error message.

v160.0.11

  • [WPF] IWizardHost now has a NotifyValidityChanged method, which does what it says on the tin.

v160.0.6

  • [WPF] Bugfix: InlineReferenceFields ignored the value of their searchMode constructor parameter.
  • [WPF] Generated FooContentController.CreateBar(choices) methods for lookup references now always set searchMode to Combo if choices is not a TypePrefixSet (i.e. generated by GetAll). This ensures that the provided choices set is actually used (searchMode: Search ignores it).
  • [WPF] Bugfix: VirtualisedSet's indexer would sometimes raise an IndexOutOfRangeException in mysterious circumstances, crashing the application.

v160.0.5

  • [WPF] EnumField<T> has a new constructor that allows the captions of its dropdown items to be customised with a new dictionary parameter. Any missing entries will use their enum member names as before.
  • [WPF] Bugfix: EnumView would let users type into its textbox portion, causing an exception to be thrown if the typed value was not one of the choices.

v160.0.4

  • [WPF] Bugfix: The previous change was incomplete due to some fields failing to notify of their validity changing when invalidated.

v160.0.3

  • [WPF] Content and list row screens will now invalidate all fields whenever an entity property's value changes, instead of invalidating other fields whenever the validity of another field changes. This fixes a bug where some fields' smarter validation logic was preventing this feature from working at all.

v160.0.2

  • [WPF] Fixed a bug preventing default shell resources from being loaded, resulting in Instagile having neither a minimum lightbox size nor a minimum window size.

v160.0.1

  • [WPF] Fixed a bug in Resizer causing it to temporarily produce strange sizes like (0,0) or (your entire screen size, doubled). This had knock-on effects like producing tiny or huge lightboxes in TabbedShell applications - clearing preferences will hopefully fix that for anyone who's experienced it.

v160.0.0

  • [MODEL] The metamodel and editor now support 'model features', groups of related model objects which implement data storage for built in runtime features. Feature entities/attributes can be edited (and used by the application for its own purposes) but cannot be removed without removing the feature.
  • [MODEL] The section view now supports drag-drop ordering of sections themselves. As requested, section summaries are also more Satanic.
  • [MODEL] Editor commands now support optional enablement based on the current node tree.
  • [MODEL] Added a new entity command, "convert to relationship" - this turns an entity which is being used as a many-to-many into a relationship by collapsing the relationships on either side.
  • [MODEL] Bugfix: Adding attributes to an opened entity didn't refresh its list.
  • [MODEL] Bugfix: Deleting entities didn't remove their sections from the internal editor datastructures (leaking memory and potentially causing later issues).
  • [MODEL] Bugfix: Pressing key combos like ctrl-z would be treated by the treeview as a 'z' and added to the filter.
  • [MODEL] Bugfix: Entities and sections added after the initial model load didn't correctly filter/display their children.
  • [ORM] Breaking: RelationshipProperty.CurrentEntities has been removed. This is part of the work towards the next wave of relationship improvements - it's no longer going to be possible to ask the ORM 'give me all the entities in this collection' unconditionally. You'll need to go through the public API of e.g. IEntitySet or IQueryable and do partial lookups which can run in the datastore.
  • [ORM] Bugfix: NullablePrimitiveAttributeSpecification.In did not produce a criteria tree appropriate for translation into SQL.
  • [ORM] Replacement with EmptyText will now happen for whitespace-only Text values as well as for null and empty ones. This is consistent with the existing behaviour of trimming calculated string values, and removes the need for a redundant Trim call within calculations (making it more often possible to use FormatOverride).

v159.1.1

  • [MODEL] Bugfix: Snapshot comparison was failing, leading to less-efficient model optimisation.

v159.1.0

  • This release requires an extension update.
  • [MODEL] Added new app-level setting "Default Entity Text" - if set, this will be substituted for entity GetText() which returns null/empty.
  • [MODEL] Fixed the attribute count displayed in the app node.
  • [MODEL] The progress bar is no longer huge. This means it no longer has huge guts.
  • [MODEL] Implemented snapshot diffs for Relationship and Key.
  • [MODEL] Bugfix: model upgrades to v5 were producing needless empty change events.
  • [MODEL] Bugfix: MoveRelationshipSide event processing produced a subtly incorrect internal state, setting up the snapshot for later failure if more events were processed.
  • [WPF] LIRFs will now always default to Search mode if given a choices set of non reference data.
  • [WPF] SuggestionBox now traps errors in the user-coded suggestion function.
  • [WPF] ReferenceDataController was broken - opening a data type would produce an error.

v159.0.0

  • This release requires an extension update.
  • [MODEL] New model file version v5 - the Section parameter to ChangeAttribute and ChangeRelationshipSide events has been removed, replaced with Move events which specify both from and to values. This simplifies the editor (or will, once the old event versions are removed) and allows more granular optimisation.
  • [MODEL] Editor tree view and property grids now respect theme colours.
  • [MODEL] Editor tree view no longer swallows underscores and transmutes them into accelerator keys.
  • [MODEL] Fixed the ordering of properties within sections in the new tree view (which was off by one 'generation' of events) and in the section summaries (which was totally wrong).
  • [MODEL] The order of events displayed in the app node was newest-to-oldest until you made a change, then reversed! Now it starts and stays oldest-to-newest.
  • [MODEL] Length and Precision fields on attributes no longer act oddly - they can be set back to default if data is entered, and they won't lead to crashes when changing attribute types. Decimals now get a useful default length/precision instead of 255,0.
  • [ORM] Azure LogAnalytics log provider now lets you configure whether to throw exceptions on failed logging.
  • [ORM] Added PersistenceManager.TryGetByID as an alternative to GetByID's throwing of ReadFailureExceptions when an entity is not found.
  • [ORM] Bugfix: export didn't correctly navigate through null references, particularly when exporting to Excel.
  • [ORM] Bugfix: IValue conversion didn't accept model-side updates if the view-side value was in a non-converting state. This manifested as The.WPF ValueFields being unable to have invalidity cleared from the model side.
  • [SQL] SQLEntityStore no longer accepts a constructor parameter to "disable auditing" - this was poorly named, as it disabled both accurate determination of the authenticated user and the actual separate recording of change data in AuditLog/AuditValue tables. Audit will soon be controlled at the model level instead.
  • [SQL] SQL timeout is now specified as TimeSpan instead of integer seconds (though it still only has second precision). The default timeout is now 60 seconds, up from 30.
  • [SQL] Added slow query logging anything that runs over 10 seconds will produce a warning. This can be configured or disabled (by setting it to TimeSpan.Zero).
  • [SQL] Some types which were still in namespace The.SQL have moved to The.SQLServer
  • [WPF] Hella breaking: The.WPF.DelegateCommand is now The.WPF.Shell.ShellCommand, and now takes a mandatory ISurface parameter to automatically handle errors. For too long have we been subject to the tyranny of ever needing to remember things.
  • [WPF] Also breaking: sections now require an ISurface (for the same reason that everything else does).
  • [WPF] Search screens used to show a Reset Criteria command, which was really just one of their inner Criteria screens' commands. Now they have their own higher-level thing named Reset Search which also clears the sort on their associated List.
  • [WPF] DatePickers now have a tooltip which displays the long date string from your configured CultureInfo.
  • [WPF] The set virtualisation code used by list UI now stores WeakReferences of pages at a time, maintaining a strong reference to only the last N (5) pages. This means that ListRow viewmodels will be unloaded as the user scrolls away, at least if garbage collection is taking place. If each page is in its own context, this would also unload the underlying ORM data, but current entityset implementations don't do that.
  • [WPF] IWizard<T> has a new OnFinishing method that is called only once, when Finish is clicked.
  • [WPF] Lightboxes in TabbedShell now show a visual indication of how many are stacked on the current screen.
  • [WPF] Blob fields now deal directly with byte-array data instead of using conversions to a viewmodel type.
  • [WPF] ValueField's .Text implementation - used by subtitles and readonly fields - now delegates to the underlying lens, meaning that Attribute-based lenses use our custom formatting.
  • [WPF] Bugfix: Showing or reordering a criteria screen's tabs when one of its basic criteria was invalid would raise an error.
  • [WPF] Bugfix: Using multiple LIRFs with CanCreate in the same context could lead to some relationships being overwritten if multiple entities created with them had relationships to the same reference data type.

v158.0.0

  • [MODEL] New tree-based UI (it isn't finished, so you can switch back to the old UI with a setting for now). The new UI is based around a hierarchical view on the left and a single editing pane on the right. To search within the treeview, select it and start typing. Whenever a kind of model element (the app itself, entities, sections, properties) appears on the screen, you can right-click it for a context menu or double-click to jump to that node in the tree.
  • [MODEL] Editor embedding now involves providing a formalised IEditorHost instead of a bunch of adhoc properties and events. The host and its interface properties are each optional if your embed scenario is ok with default behaviour. The IEditorHost can store editor settings, accessible via the gear icon which used to edit app-level model data (the app data is now in the main UI). In the case of VS embedding, they're saved to your visual studio hive.
  • [MODEL] Editor theming has been improved. It works in the designer now, and it's simpler to access - you call Theme.Change(ITheme), supplying an interface that specifies a bunch of resource keys. The actual resources can then be defined in XAML or otherwise - see The.Model.Editor/Themes/Default.xaml for an example. This also fixes the problem with some elements not responding to a VS dark theme.
  • [MODEL] Editor dialog boxes can now be cancelled with Esc.
  • [MODEL] Added a "copy entity" editor command.
  • [MODEL] Sorting by relationships is now supported, and some bugs have been fixed in the sorting UI.
  • [MODEL] The editor now allows duplicate section names (though they'd better be temporary if you want it to generate valid WPF UI).
  • [MODEL] The editor now measures and displays its own loading progress, so we can see whether it's getting slower.
  • [MODEL] Implemented "optimisation barriers" in the optimiser, conceptually similar to "memory barriers" in a CPU; this replaces the "hoisting" heuristic, which fixes a whole class of reordering/combination bugs.
  • [MODEL] Bugfix: empty DiagramNumbers weren't being parsed correctly by the editor.
  • [ORM] AppDataPreferenceStore's ILoggerFactory dependency is now optional - it's just used to log a failure to load existing prefs.
  • [ORM] Added a built in ILogProvider for Azure Log Analytics. You can use it in an application with ILoggerFactory.AddAzureAnalytics().
  • [ORM] Added a Func<specification> constructor to Reminder which let you supply a nondeterministic spec generator in order to use stuff like use DateTime.Now.
  • [ORM] EntityCollectionProperty<T>.Contains(T) now returns false when its argument is null.
  • [ORM] Bugfix: EntitySet.AddRange would only add one item from its input to the set.
  • [ORM] Bugfix: ImagePresenter's image transformation methods (CreateThumbnailAsync, GetRotationAsync, etc.) were not disposing of all objects representing GDI+ handles, potentially causing resource leaks.
  • [ORM] Bugfix: PersistenceManager's logging of read failures now includes a stack trace.
  • [SQL] The CreateIndexes script will no longer drop indexes before creating them.
  • [SQL] Generated index names that would have been too long for SQL Server (128 characters) will now be truncated to a unique but deterministic form.
  • [SQL] SQLEntityStore now allows for server clock drift when doing internal date comparisons - not searches, but the kind of stuff that's used for maintaining set stability. There's currently a hardcoded threshhold of five seconds, which gives you a pretty good chance of read-your-writes in practice.
  • [SQL] Version conflict detection has been expanded to cover references. If a reference was changed to the same value by a another transaction, that isn't considered an error at all anymore; if it was changed to a different value, that will be a VersionConflictException instead of a general WriteFailureException.
  • [WPF] Breaking: CreateModel's Content property is once again of type ContentModel<T> instead of IScreenModel.
  • [WPF] EntitySelector now handles INotifyCollectionChanged.CollectionChanged and IEntitySet<IEntity>.SetChanged on its Choices property.
  • [WPF] Minishell now supports multiple surfaces, each of which can host a stack of modal screens - or standard screens displayed as modals. Its window drag behaviour has been considerably improved, and rendering artifacts should be fixed.
  • [WPF] Display and Create views now allow click-through if overlaid on some other control.
  • [WPF] Bugfix: EnumField would crash if validation rules were added to it.
  • [WPF] Bugfix: Two methods in SQLDocumentStore were failing to dispose of streams they created, potentially causing resource leaks.

v157.8.5

  • [ORM] When nontransient entities with relationships to transient entities were saved, MarkUnchanged() would be called on the relationship; this could incorrectly set its OriginalValue[s], later triggering error messages to be logged when a clone detected that OriginalValues were Creating.

v157.8.4

  • [WPF] FlaggedEnumToBooleanConverter now supports ConvertBack on bool values, values that implement operators true and false, and values that are implicitly convertible to bool.

v157.8.3

  • [ORM] When relationship properties detect errors indicative of bad cloning/graph manipulation, they now log errors instead of throwing exceptions.
  • [WPF] Bugfix: InlineCollectionFieldBase.Select() was called from an ICommand without using HandleErrors - a potential crash if an exeception was thrown by the ORM.

v157.8.2

  • [WPF] Automatic reporting of notifications-as-logs in TabbedShell. Switching on The.WPF.Shell will give you info/warning/error logs for the equivalent notification levels.

v157.8.1

  • [WPF] The.WPF.Screens and The.WPF.Shell logging is now more consistent/helpful.

v157.8.0

  • [WPF] ImageField now supports flip (reflect) transformations.
  • [WPF] Bugfix: ImageField would do nothing if a file was selected in its Upload file picker, and raise an error otherwise.
  • [WPF] Bugfix: FileField and ImageField value changes were not reflected in the user interface.

v157.7.1

  • [EXPORT] Bugfix: The LogError call which was meant to capture ExportManager bugs was, itself, buggy.
  • [SQL] The default query timeout on SQLDatabase is now 30 seconds instead of infinite.
  • [WPF] Bugfix: EntityLink, when left-clicked when NavigateCommand was unset, or when middle-clicked regardless of that property, was incorrectly checking read access to determine whether to open the linked entity for editing.

v157.7.0

  • [ORM] The Copy method on generated entities is now virtual.
  • [SQL] The SQL Agent job is now scheduled once per day by default instead of four times a day, and will only remove session tables older than one day.
  • [SQL] Optimised the implementation of GetPage() on query-based sets using some fancier SQL.
  • [TEST] The test suite for IEntitySet implementations is now more accurate.

v157.6.1

  • [WPF] Bugfix: Scrolling through a list which changed as you scrolled, with a change aligned on a page boundary (e.g. changing to X where X%25==0), would cause VirtualisedSet to load an empty page and fail to handle it correctly. This surfaced as ArgumentOutOfRangeException.

v157.6.0

  • [ORM] Added a new set of read optimisations to replace the old "enum cache". Using GetByID<T> or GetAll<T> repeatedly in the same IEntityContext for the same T will now return the same data until a T in that context is saved, and the TypePrefixSet returned by GetAll will retain handles to its data if repeatedly enumerated.

  • [ORM] Fixed a bug preventing timing of write operations in logs.

  • [TEST] Added NominalOrderer, an ITestCaseOrderer which sorts tests by name. This lets you write a unit test class along the lines of

    [TestCaseOrderer(nameof(NominalOrderer), "The.Xunit")
    public class OrderedTests {
      [Fact] Test1_Foo() { }
      [Fact] Test2_Bar() { }
    }
    

v157.5.0

  • [TEST] The.Xunit now includes mocks for IShell, ISurface and IWizard.
  • [WPF] The view of a ValueSectionedCollectionField subtype can now be customised.
  • [WPF] Setting EntityLink's ToolTip property will now override the default behaviour of displaying its entity text.

v157.4.2

  • [WPF] Bugfix: Removing columns using the ManageColumns dialog wrote the wrong values to preferences.

v157.4.1

  • [WPF] List column preloading now supports collections - it will preload pages where none of the counts are greater than some threshhold (currently 3).
  • [WPF] Bugfix: list column preloading was applying to transient relationships, which of course doesn't work.
  • [WPF] Bugfix: 'Manage Columns' would be displayed on some context menus even if a list model's CanManageColumns flag was unset.

v157.4.0

  • [ORM] SelectByRelationship operation can now load related data for multiple entities in a single query.
  • [ORM] Fixed multiple bugs preventing reference hookup from working - when the latched entity was loaded it would trigger a GetByID before it could emplace itself. This was introduced fairly recently during relationship robustness improvements and could have been a major performance issue.
  • [WPF] Virtualised lists now preload pages of related references according to the columns visible in lists, obviating subsequent asynchronous lookups. You can override GetPreloadedRelationships() on ListController to add to or alter the set of preloads.
  • [WPF] Generated list rows now use lazy fields for calculated properties, avoiding an automatic calculation during page loads.
  • [WPF] SuggestionBox now supports a null SelectedItem, which will be treated as empty string for selection purposes.

v157.3.4

  • [WPF] Textbox-based criteria fields had regressed to no longer be "deactivatable" by deleting their text when ValueField was introduced. It's not that the new base field was any less capable of representing a default, but the criteria definitions were changed to no longer go through FieldFactory, which had been supplying initialValue:="". Now the Factories.tt template does this itself.

v157.3.3

  • [ORM] Remotely removing either collection members or reference values now correctly deletes in all states even more than previously.

v157.3.2

  • [ORM] Live properties are no longer proactively calculated during cloning - this is a waste of time because they'll just be calculated when you next inspect them anyway.

v157.3.1

  • [ORM] Added more error-checking and a number of bugfixes to the code around removing entities from relationships. This was occasionally surfacing as errors like "illegal state transition" after repeatedly removing and then re-adding things to lookups, as well as in more obscure situations produced by shobiz wizards. Specific fixes:

    • Adding back collection members which had previously been present now also remotely adds them back to the other side, causing reference update cascades if necessary.
    • Removing single members and clearing/replacing all members of collections now share an implementation and correctly undelete in all states.
    • Remotely removing either collection members or reference values now correctly deletes in all states.
  • [WPF] Currency search min/max fields no longer apply hard to control "live formatting".

v157.3.0

  • [ORM] Cloning symmetrically related entities into even an empty context would incorrectly detect inverse relation members as members of forward relations, leading to erroneous rowstates in the target context. This could then lead in turn to erroneous row-state-based calculations and therefore an exception later in the cloning process.
  • [ORM] Added another diagnostic to more comprehensively detect rowstate errors during clones.
  • [ORM] Fixed a stack overflow when DeleteAll was called on non-navigable references.
  • [SEC] Licensing now uses a more reliable method of verifying entrypoint hashes. Build-hash licensing has also been brought under test.
  • [WPF] Create screens now show a progress bar when saving (like Display screens).
  • [WPF] If a Create screen is closed while saving, the save will be completed first.
  • [WPF] ProgressController now correctly indicates cancellation when shouldCloseWhenCompleted is true.
  • [WPF] Indirectly-editable hyperlinks to reference relationships in inline lists now work - except if they're relationships to reference data, in which case there is no link.
  • [WPF] Adding relationship criteria twice no longer re-uses criterion instances.
  • [WPF] The way EntitySelector handled clicks was broken: the "open the selector" behaviour took precedence over middleclicks on links, over right click to bring up the context menu, and even worked when the control was readonly. Now it's more, for want of a better word, selective.
  • [WPF] ListOptions has a new SuppressDefaultSorting option; set this to true to suppress the default ListController behaviour of falling back to the entity's default sorting when no sorting columns are selected, e.g. to allow a custom set's built-in ordering to take effect.
  • [WPF] EntitySelector now has a FallbackText property which is passed through to the underlying EntityLink if one exists.
  • [WPF] EntitySelector now supports a SelectionChangedCommand property which is fired after its selection changes (as you might expect).
  • [WPF] Lookup collection fields no longer require an extra click on an explicit Add button to add items - you just use the selector.
  • [WPF] Add a minimum width for DatePickers to the Inky theme.

v157.2.8

  • [WPF] RecentItems sidebar no longer automatically opens when a new item is added.
  • [WPF] Through-relationship search fields no longer say (0 selected) when more than 0 are selected.
  • [WPF] Range search fields no longer grow/shrink their entry boxes weirdly - this was most prominently an issue with DateRangeView.
  • [WPF] Date-only ranged searches now correctly search through the entire range of timestamps in a day. They clamp to 0 at the From end and 23:59:59 at the To end.
  • [WPF] If the framework was initialised on a background thread, its culture overrides (date formatting, etc) didn't apply to conversions which took place plurely inside a UI with no VM involvement. The.WPF now alters any existing main thread to use our custom culture.

v157.2.7

  • [WPF] Bugfix: Navitating to a new entity through an EntityLink would open a DisplayController instead of a DisplayModalController.

v157.2.6

  • [DOCUMENTS] Added some error and trace logging for The.Documents.
  • [DOCUMENTS] Improved error handling; document attributes can now deal with failed metadata lookups, and thumbnailing should propagate errors instead of breaking its state machine and hanging.

v157.2.5

  • [ORM] Bugfix: Cloning partially-reified collections into a target context that contains a copy of the collection with extra information now clones the unreifiedness of the source context. This prevents spurious relationship insertions and removals caused by reconciliation.

v157.2.4

  • [ORM] Bugfix: Cloning an entity into a target context that contained a copy of that entity with non-overlapping partially-reified non-navigable collection members would incorrectly reconcile the source and target collections, leading to a missing structure in the target context which would delete some relationships when saved.

v157.2.3

  • [ORM] Bugfix: LazyLoad would incorrectly attempt to perform persistence operations when called on a non-navigable reference to a transient entity.

v157.2.1

  • The.Xunit has made it from perpetual prerelease to beta - it still depends on prerelease versions of xUnit itself, but we now have release-mode beta builds pushed to \acdc and MyGet, which can be used in applications' unit test projects.

v157.2.0

  • [ORM] Rewrote ImportManager.CalculateProperties. Instead of a 'readahead task count' there's now a max thread count, which can be as low as 1 (previously this would deadlock); by default it's Environment.ProcessorCount. The recalculator no longer spams the task pool in an ill-conceived attempt to overcome latency. As well as being more reliable, it uses modifiedOn as an optimisation to minimise double-saves during the calculation run.
  • [ORM] Fixed another remote-update bug - adding an entity to a collection of nonnavigable references didn't remove it from other unloaded navigable collections. This would manifest as a foreign key violation on save.
  • [ORM] Fixed a bug when creating a new object, cloning it, saving the clone, then cloning it back - the original version would not register as saved. This was causing an inability to creat new places in SHOBiz.
  • [TEST] Fixed many of the slowest unit tests.
  • [WPF] TabbedShell now has a main-thread exception handler which logs unhandled errors and probably doesn't crash.
  • [WPF] Fixed wizard progress bar not showing.

v157.1.1

  • [WPF] Range criteria fields were invalid by default - we didn't notice because of the broken validation on ValueField.

v157.1.0

  • [EXTENSION] Generating templates was broken by M.E.L. It should work again now.
  • [ORM] Bugfix: Saving non-navigable or partially-reified collections via references pointing to them would, while saving correctly, leave the context in an uncloneable state.
  • [WPF] FieldBase<T> now has a virtual OnRulesChanged method, which ValueField overrides to recalculate its own validity. This fixes a bug where a ValueField would begin valid and never become invalid unless its value was changed somehow.
  • [WPF] LazyField<T> now raises PropertyChanged when its inner value becomes available (for example when it is displayed in the UI using .Content). This bug was preventing some invalid fields from invalidating lists or sections which contained them.
  • [WPF] SuggestionField did not display any chrome for validation errors.

v157.0.0

  • [ORM] Improved some log messages and parameters.
  • [SEC] Authorisation is now cached for an IPrincipal. This makes it feasible to implement remote authorisation at some point.
  • [WPF] SuggestionBox (and by extension SuggestionField) will now silently ignore null or whitespace-only suggestions.
  • [WPF] Collection summaries in list cells now have the entity's default ordering applied.
  • [WPF] Calling Convert on an IOwnedValue now returns another IOwnedValue.
  • [WPF] Breaking: ValueFields now implement the 'not invalid when unchanged' rule internally.
  • [WPF] Breaking: Some now-unnecessary overloads in FieldFactory have been removed.

v156.0.5

  • [WPF] ListModel now raises some of the changes the first time List is set, to avoid async issues with the annoying way it initialises.

v156.0.4

  • [WPF] ListModel no longer raises propertychanged redundantly the first time that List is set.

v156.0.3

  • [WPF] Keys in The.WPF.Shell.Resources can now be overridden by applications if they explicitly include The.WPF/Shell/Resources.xaml in their app resource dictionary before it's loaded implicitly one of the builtin shells.
  • [WPF] TabbedShell's min width and height are now customisable using Resources.WindowMinWidthKey and Resources.WindowMinHeightKey.

v158.0.0

  • [WPF] Tweaked the display of collection cells.
  • [WPF] Fixed INotifyPropertyChanged from fields or sections on Content screens causing nullreferences if the screen init was not complete.
  • [WPF] Fixed ListModel<T>.CurrentOrdering raising propertychanged even if it was set to its current value.

v156.0.2

  • [ORM] Bugfix: Cloning back a collection into a context which already contained that collection could, if the collection contained a member added in the modal/source context and a second relationship existed between the same two entities in the target context, leave the relationship structures in a subtly incorrect state which, although appearing to save correctly, would at that time be in a less-subtly incorrect state, revealing a failure to to serialise some of the changes.

v156.0.1

  • [EXPORT] PropertyPath.DeserialisePaths no longer throws exceptions for invalid paths; these will simply be excluded from the results and a warning logged for each instead.
  • [EXPORT] Bugfix: Errors raised from ListController.Export could bring down the application.
  • [LOGGING] The.Security now has logging.
  • [LOGGING] Relationship cloning now has trace logging.
  • [LOGGING] Removed the WPF.Composition.Builder.WithValidationLogging method - the same information is now available at LogLevel Debug.
  • [WPF] Wizards are now more tolerant of martial leaders.

v156.0.0

  • [LOGGING] The original logging system is gone, replaced by the Microsoft.Extensions.Logging abstraction. To configure logging supply an ILoggerFactory to Builder -

    for example "new LoggerFactory().AddConsole().AddDebug()"; a number of log targets ("providers") are available on NuGet, as are adapters for other systems like Serilog and NLog. To log in an application, access the Logger property on various base classes or IServices.CreateLogger<ForType>(). ILogger instances can be shared between object instances, but if you're going to do a lot of logging the higher-performance option is to have a logger per long-living object. using Microsoft.Extensions.Logging; will add convenience methods. In general logging is now enabled/disabled for specific hierarchical categories and levels, so methods like Builder.WithPersistenceLogging() are gone. We now have far more comprehensive logging across the framework which can be enabled (and perf-controlled) at runtime. Some highlights:

    • Most parts of the system log any exceptions they encounter as Error or Warning.
    • Security and licensing errors can also be reported in logs, with the detail that's deliberately missing from user-exposed exceptions.
    • LogLevel Info in namespaces will log routine operations along with timing metrics.
    • LogLevel Debug is for the internals of operations, for (obviously) debugging. We'll implement debug logs opportunistically as needed.
    • LogLevel Trace provides full actual application data, e.g. entity data dicts and sql queries/results - this is slow and can compromise data security, so don't enable it indiscriminately. Some categories with trace-level logging: The.SQL.SQLEntityStore, The.Persistence.PersistenceManager, The.WPF.Wizards
  • [SEC] Backend authorisation, if enabled, was checking ReadAccess instead of WriteAccess for writes!

  • [SQL] The.SQL.DatabaseFactory existed mostly to compose logging under the old system. It's gone, and providing the rest of its former convenience

    functions is a new type The.SQLServer.SQLDatabase which specialises IDatabase to work with a SqlConnection.

  • [WPF] Wizards now detect and report potential errors like calling PreviousPage() between pages (you don't want an infinite loop, I assume).

  • [WPF] When detecting an error that prevents further navigation, the wizard used to cancel itself, hiding the error. This was visible to users as the screen

    just flashing with no apparent cause. Rather than this behaviour, WizardController now displays the notification normally but puts itself into a disabled state where the only available action is cancellation (or closing the tab).

v155.3.3

  • [SEC] Identity objects now have debug text (useful for the shobiz statusbar).
  • [SEC] One call in PersistenceManager.SaveForest was failing to respect the IPrincipal of an IEntityContext, meaning that CreatePreauthenticatedContext didn't quite fully override standard auth for saves.
  • [WPF] ID, createdOn, createdBy, modifiedOn and modifiedby are no longer AdminOnly. This means that you can add them to lists and search criteria.
  • [WPF] Bugfix: CollectionSelector's default template drew its Background brush over the content.

v155.3.2

  • The.Utility now creates annotated Git tags instead of lightweight ones, allowing them to be pushed with 'git push --follow-tags'.
  • [ORM] Sorting by references was failing on null references for the in-memory provider.
  • [WPF] All ProgressBars in the framework are now themeable via default styles.
  • [WPF] Bugfix: SearchController was incorrectly requesting its list be 'open for edit' when the user had only read permission for the entity type.

v155.3.1

  • [ORM] Converted IValues now store a "local value" of the target type. As long as the source-type value is such that, when the target-type value is converted to it, it does not change, then the local target-type value will be read without updating from the source-type value. For the laity: databinding "5" to 5 will now let you type "05" without immediately deleting the 0.
  • [WPF] Collection-summary cells in lists can now display multiple items (comma-separated, up to 5 for now).
  • [WPF] Section headers in Inky are now clickable across their whole width, rather than just on the title or button chrome.

v155.3.0

  • TheFramework.sln can now build in VS2015 when VS2017 is installed, but requires the latest sdk updates (https://go.microsoft.com/fwlink/?LinkId=827546 and then https://go.microsoft.com/fwlink/?LinkID=827524). This branch does not build in VS2017.
  • [REPORTS] ReportManager now avoids referencing the type VisualBasicCompilationOptions unless you actually use VB, which makes its use from T4 more reliable.
  • [REPORTS] ReportManager.Generate(), .Compile() and .Validate() now support an optional list of extra assembly references - more reliable than hoping T4 will put everything in one directory, which it no longer does as of VS2017. Assemblies containing VM types will be included automatically.
  • [WPF] WizardController can now be constructed with a Func<IWizard> or a Task<IWizard> - in these cases it will construct the wizard asynchronously and show a loading screen while doing so. This allows some wizards to have expensive one-off init processes in the natural place - their own constructor.

v155.2.1

  • [ORM] Added some autoproperties and [DebuggerStepThrough] to reduce debugging friction.
  • [WPF] CollectionSelector now supports the Background property.

v155.2.0

  • [WPF] ValueInlineCollectionField now lets you supply the extra optional constructor parameters which ValueSectionedCollectionField can use in order to pass them through.

v155.1.0

  • [WPF] Added ListModel.CanManageColumns - if changed to false, the user will be locked out of removing/adding/reordering columns (including via context menu actions). This does not prevent resize or sort.
  • [WPF] ListController overrides can now return null from CreateField to suppress some column entirely. Not an ideal API but it fills an immediate need.

v155.0.1

  • [WPF] ManageColumns dialog rewritten to hopefully eliminate first-column shenanigans.

v155.0.0

  • [WPF] Display.TryClose() was incorrectly implemented using IScreenController.Close instead of ISurface.Close.
  • [WPF] IScreenController.Close and .IsOpen have been renamed to Deactivate and IsActive to better reflect what they actually do.
  • [WPF] Added FilterSuggestions property to SuggestionBox and SuggestionField - if this is changed to false, the control wil not filter its suggestion list based on current entered data.
  • [WPF] Lightbox titles can no longer overlap and disable the close button.
  • [WPF] The lightbox close button now has a tooltip (the name of the command it will invoke, most likely but not always Cancel).
  • [WPF] CellCollectionControl is now thread-safe.
  • [WPF] FileControl did not update its ui when the file changed due to a broken workaround.

v154.0.0

  • Bugfix: The.Utility was calling NuGet.exe with output paths that made sense for a pre-release version.

  • [ORM] Commas are now filtered from the section name in generated create section functions.

  • [ORM] Bugfix: Cloning a relationship to a loaded but non-present collection would lead to the cloned collection missing any tracked kernels from the original collection. This would lead to problems if the collection were later modified.

  • [ORM] Bugfix: Cloning back a collection into a context which already contained that collection could, if the collection was related to references which were altered in the modal/source context, leave the relationship structures in a subtly incorrect state which, if elements were later removed from the collection, would at that time produce a less-subtly incorrect data structure which, if subsequently saved, would fail to serialise the changes.

  • [ORM] In the past, including the extremely recent past, we've suffered bugs along the lines of "a clone goes wrong, producing an object graph which later fails to operate according to OH&S". Added asserts immediately after cloning to enforce these invariants.

  • [WPF] Added an optional "foreground" parameter to IScreenController.Display - if false, the screen will be opened in the background. This was already possible by using ISurface.Activate, but the new version preserves viewstate.

    Lists support foreground=false via rightclick->"Open In New Tab", and EntityLink supports it for middle-click.

  • [WPF] New convenience constructors for FieldsSection.

  • [WPF] Breaking: ListRowBase no longer has an IsSelected property; it would not reliably stay bound in the face of virtualisation.

v153.0.1

  • [SEC] IPrincipal.CheckAdmin() was throwing.

v153.0.0

  • [SQL] Fixed queries over legacy columns when using legacy persisters.
  • [WPF] IWizardHost.ShowAsPage extension method no longer displays SectionControl chrome on the wizard page.
  • [WPF] Search screens were ignoring ApplyGlobalSpecification when no criteria had been entered.

v151.2.1

  • [WPF] FieldsSection is now one-way serialisable

v151.2.0

  • [WPF] Cleaner subclassing API for FieldsSection.

v151.1.0

  • [ORM] Improved partial reification scenarios: otherside discovery can now totalise collections, and latched refs wait bidirectionaly. In laydev's terms:

    * loading entities with references now immediately adds them to already-existing collections, as well as the other way around
    * if this happens to all entities in a collection, the collection will become IsPresent with no further lazy loading
    * it doesn't matter whether you load the references or the collections first
    * this also works with ref-to-ref relationships, but not collection-to-collection
    

    These are significant optimisations in some cases, and better support "preloading" of data pages.

  • [SEC] IServices has a new CreatePreauthenticatedContext() method that can be used to get an IEntityContext that will use the provided Identity (instead of seeking one from the SecurityManager as normal).

  • [SEC] 'Scoped' contexts used by plugins now record the purpose of the plugin as their identity.

  • [SQL] Queries with multiple Skip and Take calls in sequence are now supported.

  • [WPF] ProgressController now displays timestamped logs.

v151.0.0

  • [ORM] The.Composition.Root is now created by supplying plugins, rather than managers - it makes the managers internally itself.

  • [ORM] Removed external configuration of 'enum caching' - this feature had been gutted over several releases and is now only caching GetByID of reference data. It's disabled for now and needs refactoring.

  • [ORM] Moved EntityCollectionProperty<T>.SetChanged into EntityCollectionProperty.

  • [ORM] Generated entity types and EntityKernel are now one-way serialisable for the purpose of description or use as a key in IWizardHost.CalculateIfChanged.

  • [SQL] Procedure getUserInfo() now 'works' without setUserInfo being executed first - at least, it returns SYSTEM_USER like it originally did.

  • [WEB] Composing services and middleware is now a little more rigorous and hews better to the ASP.NET Core conventions. There's a single core method (overloads notwithstanding)

      IServiceCollection.AddTheFramework(Builder/Func<IServices>)
    

    This is necessary to use any The.Web features, and sufficient (as of this release) to use the framework as a production-ready ORM for a conventional MVC website. Other features are provided as Add/Use extension method pairs on IServiceCollection/IApplicationBuilder respectively: AddTheProxyServer()/UseTheProxyServer() - Sets up an endpoint for persistence remoting. Possibly production-ready, modulo testing. AddTheSPA()/UseTheSPA() - Hosts frontend scripts and an API for entity access from the scripts. Not production-ready. AddTheAdminSite()/UseTheAdminSite() - Incorporates the SPA functionality, and also serves an endpoint for browsing data with generated UI. Not production-ready.

  • [WEB] The.Web.nupkg now includes .d.ts files for the scripts it serves up at /the when using its SPA middleware. The typings can be found next to The.Web.dll when a project referencing it is built; however, they are present for reference by tsconfig.json, not for inclusion in a published application.

  • [WPF] Added a 0-arguments overload of ListOptions() and a 1-arg overload of ScreenManager.CreateList.

  • [WPF] Fixed List concurrency issues:

    * If a list's rows were loading slowly and you opened context menus on/moused over rows which had Row Commands, you could get a non-dispatcher view update error.
    * If multiple slow refreshes took place 'at the same time', perhaps because of switching search criteria, the order of execution was not guaranteed.
    * Exacerbating the above issue, there were circumstances where a list's set load (which means, in some cases, a DB query) would be synchronous! Specifically, calling Refresh() _before_ the current set had finished loading (or begun, in the case of non-visible lists) would block - only the subsequent UI-update stages of the refresh were nonblocking.
    * Task Refresh() and Task EnsureLoaded() now verify dispatcher access to catch what could otherwise be quite mysterious errors. 
    
  • [WPF] ContentModel and CriteriaModel are now one-way serialisable (for, again, the sake of wizards).

  • [WPF] ContentModel.Fields is now public (previously only .Sections was available).

  • [WPF] SidebarModelBase's constructor has a new name parameter, which determines the sidebar's initial title and the preference key for its IsExpanded property.

  • [WPF] Lists now display a count of their rows in the bottom-right corner.

  • [WPF] The Background property of MultiCommandButton now controls the background colour of its dropdown, and the buttons added to that dropdown by the shell no longer reset their own backgrounds. This should make menus more themeable - "floating buttons" is now a feature of the Inky theme rather than a default.

v150.3.2

  • [REPORTS] Bugfix: Some combination of project.json and T4 didn't work due to a Roslyn packaging bug; the Roslyn version has been bumped to get the fix.

v150.3.1

  • [WPF] Bugfix: the Reset Criteria button on search screens did not necessarily use the changed criteria to re-execute a search.

v150.3.0

  • [WPF] Added SelectOrCreate functionality, in the form of a canCreate flag, to LSCF and ESCF as well as LICF (which passes it through to either).
  • [WPF] LookupSectionedCollectionField (LSCF) is now more subclass-friendly.
  • [WPF] EnumSectionedCollectionField (ESCF, the one with the checkboxes) has slightly redesigned filter UI to make more room.
  • [WPF] EntitySelector.SelectIcon can now be changed (via e.g. theme) to replace the default magnifying glass.
  • [WPF] Bugfix: EntitySelectors would sometimes lose their icon entirely.

v150.2.1

  • [WPF] Bugfix: LIRF/VIRF had a display glitch when unbound, rendering with a spurious error border.
  • [WPF] Bugfix (esoteric): when adding validation rules which could trigger dependency updates to a FieldBase-derived IField, these rules would apply before default rules set in field constructors if those rules did not trigger dependency updates, preventing the early-accept rule used by 'bound' fields from applying before custom rules could take effect.

v150.2.0

  • utility gen can now do UTF-8 output and has a more comprehensive set of options. It's used as part of CI to verify our templates.
  • [WPF] Added SystemConverters.ObjectToInverseVisibilityConverter.
  • [WPF] InlineReferenceFields can now be subclassed.
  • [WPF] LIRF now has a canCreate flag in its constructor; if this is set to true, the resulting field can be used to create new entities as well as select existing ones. VIRF always has the equivalent of canCreate=true, since it's by-value.
  • [WPF] Criteria now once again assume that their fields always have non-null values. This is by-design, as null is used to signal to not apply that criteria at all.
  • [WPF] Bugfix: Search criteria template was generating broken code (separately to the change above, due to unrelated changes).

v150.1.0

  • [WPF] Search screens are now more customisable by subclasses.
  • [WPF] Bugfix: The validation error notification on Create screens was incorrectly listing all field errors as "1: 2".
  • [WPF] Bugfix: Rowcommand buttons were missing some bindings.
  • [WPF] Bugfix: Some criteria were incorrectly assuming that their fields always had non-null values.
  • [WPF] Generated criteria no longer use FieldFactory.

v150.0.0

  • Added a "2017 licence" item template to The.Extension.
  • New nuget package: The.Xunit. This contains xUnit.net extensions which were formerly in individual test projects - the goal is to provide the same facilities we use to test the framework itself to applications' own tests. At the moment, the types are generally useful rather than really Framework-specific.
  • Combined The.MSAccess and The.MSExcel packages into The.MSOffice to reduce package proliferation.
  • Renamed The.SQL package to The.SQLServer to take advantage of this name-breaking opportunity.
  • [ORM] DataContractEntityStore now supports ordering references by the text of the reference, rather than its guid (this is the behaviour of SQLEntityStore also).
  • [ORM] Both DCES and SQLES now support ordering by a hybrid of count and single-entity text for collections.
  • [WPF] The two-textbox version of numeric range criteria is back as an option, called "Min/max".
  • [WPF] ListOptions has a new 'IgnoreSortingPreferences' field. Setting this to true causes the list screen to not be sorted according to the user's existing preferences, and to not persist further sort changes as user preferences.
  • [WPF] Collection cells in readonly lists now have a smarter display - rather than just a number, they will show some elements if possible but (N items) if the collection is too big. Like reference cells, this loads asynchronously.
  • [WPF] Fixed some loading errors and performance issues related to the async cell loads (the most common symptom: cells were sometimes showing up blank in lists unless you scrolled away and then back to them).
  • [WPF] Added a user preference (accessible via the list rightclick menu) to show/hide nulls and 0s in cells.
  • [WPF] Tabs on the Criteria screen now have more room to show their name and search result count.
  • [WPF] Bugfix: Using the 'manage columns' context menu item of a list to change its ordering was ineffective.

v149.0.0

  • [ORM] Sometimes, at the end of a data import a batch of zero WriteOperations would be issued. This wastes time and, with the new security system, fails to validate.

  • [ORM] Persistence logging was broken by the new InsertData logging, and now isn't.

  • [SEC] Redefined security objects to add functionality and standardise terminology. There are three primitive objects representing security statements, all serialisable:

    Identity:  A name with meaning within a realm. Examples "AGILE\thomas" within "NTLM"; "pd75840" within "PKI"; "guest" within "unauthenticated".
    Identities are dispensed by IAuthentication, can be used by IAuthentication to sign operations, and are used as claim subjects by IAuthorisation.
    Ticket:    A _token_ used to validate authentication as some _identity_.
    Tickets are signed and verified by IAuthentication - generally by local and remote authenticators, not the same instance. Tickets are associated with a specific _operation_, which can be used for cryptographic signing - however some authenticators are able to use alternate verification mechanisms and may ignore the operation parameter. A ticket is just a statement that you are allowed to act as an identity, and if your identity is known out of band then *any* operation is valid.
    Claim:     An assertion of permission to perform some action on some object. Examples: WriteEntity Place; IsAdmin; Other `<application data>.`
    Claims are made by application or framework code. IAuthorisation accepts or rejects claims for a given identity. The authorisation subsystem is optional, and if NoAuthorisation is used then any *authenticated* users can make any claims.
    

    There's also a higher-level object for use in application logic: IPrincipal: An authenticated identity with the ability to make claims and issue tickets. Not serialisable. IPrincipals provide a permission-checking API and perform caching when safe. The IPrincipal API can be used to check authorisation or to create a Ticket for later reconstruction of the IPrincipal. There's a low level Check/AssertAccess API which operates on claims, and a high level alternative for standard checks. There are several ways to obtain principals: * SecurityManager.CurrentPrincipal - returns a principal for the current thread as determined by IAuthentication. This may change over time as users log in/out. * SecurityManager.GetOperationPrincipal(operation, ticket) - reconstructs a principal authorised to perform some operation by verifying the ticket with IAuthentication. * IEntityContext.Principal - returns the principal for the current scope (callstack), which may be privileged * (WPF-specific) <screen/field/etc subclass>.Principal - returns the principal for the UI thread. * (Web-specific) IPrincipal dependency injection - returns an HTTP-request scoped principal.

  • [SEC] Implemented remote security based on the principle that the server independently verifies a client claim. RemoteEntityStore treats the read/write commands as an operation bound to an Identity by a Ticket; a remote IAuthentication validates the Ticket, providing a Principal for IEntityStore, or rejects the request. Not all IAuthentications support being used for remoting; right now, it's available in NTLM auth, which verifies OOB that the claimed Windows user is authenticated. Next we plan to add PKI auth, which will verify that the privkey for a known pubkey was used to sign the request.

    The remote security system prevents unauthorised access, including replay attacks - but it is only secure, not private. Encryption or other forms of privacy are the responsibility of the transport channel, IEndpoint - for example when using the built-in WebEndpoint it's recommended to use HTTPS. In some applications the ability to monitor communication is required, and by separating the responsibilities this is possible without compromising access security.

  • [SEC] Authorisation is now enforced at the 'backend' level, not just the ui - SecureStore verifies that the ticket- or thread-authenticated principal has read/write access to the relevant entity types. This can be turned off using .WithInsecurelyDisabledAuthorisation(true).

  • [SEC] To enable entity-based storage of auxilliary data, plugins "higher level than" IEntityStore are now provided with a special IEntityContext which can be used for "scoped persistence". Within the scope of the plugin's call stack, security and licensing requirements are suspended - so you can use it to e.g. IMPLEMENT security, or to log a failed license check... To avoid exfiltration, the scoped context has a remoting-incapable principal - that is, this will only work on the backend.

    Right now, this facility is available for IAuthentication, IAuthorisation, IPreferenceStore and ILogger; it supplants the older Licensing.IToken mechanism some of those interfaces used. This feature will be the foundation of model 'features' - the ability to check a box and get roles or server-side preferences or audit logs added to your application.

  • [SQL] It's now once again possible to disable audit in SQLEntityStore.

  • [SQL] Calculated properties are now auditable in SQL (unless you disable audit).

  • [WPF] WizardModalController is now just WizardController, since it's not like there's a non-modal variant.

  • [WPF] Wizards should be written 'deterministically' - that is, each run of Run() must produce the same output for the same input (or call NotifyStepsChanged() to signal otherwise); in order to make this easier, the way determinism violations are detected has changed. Previously, in debug framework builds they produced hard errors, but in release mode would try to autorecover; this wasn't very effective because applications use release-mode frameworks!

    Determinism autorecovery now always takes place, and logs a warning; if a debugger is attached it will also produce a warning notification/popup. The whole autorecovery process is now more robust also, and shouldn't generally produce wrong behaviour, just extra reloads and stuff. Many unit tests have been added.

  • [WPF] New api: IWizardHost.CalculateIfChanged(input, f). This will produce derived data (by running function f) only if there has been a change in the input argument since the last wizard run on which the calculation was performed. It should help to ensure determinism and cache things like search results for performance. The comparison works by serialisation, so you can tune it using [DataContract] attributes on the input object.

  • [WPF] New api: WizardBase.CurrentHost - this lets you set up subscriptions in a constructor instead of later adding then removing handlers.

  • [WPF] New api: IMenuBuilder.AddWizardLink.

  • [WPF] Bugfix: The current step was not being made visually distinct anymore.

  • [WPF] Some generated CriteriaFactory properties are now public for advanced customisations.

  • [WPF] Restored a distinction between the default Yes/No/Unknown bool? fields and the Yes/No/Any search fields - the latter are UITrait.Constraint.

  • [WPF] Bugfix: AutodiscoveryControllerFactory would fail to discover CreateModalController override classes.

  • [WPF] Bugfix: DoOpen didn't work on hyperlinks in inline lists.

  • [WPF] Bugfix: LookupInlineCollectionField didn't work for reference data (it would let you select some checkboxes, but they had no effect on the outcome).

  • [WPF] Bugfix: Lookup/ValueInlineReferenceField didn't reliably detect reference-data for selector-mode purposes if used unbound to entity props.

  • [WPF] Bugfix: EnumSectionedCollectionField didn't correctly clone its new selections, preventing editing of reference data.

v148.1.0

  • [ORM] WriteOps are now fully inspectable through their ToString methods.
  • [ORM] VersionConflictException and WriteFailureException now both have an AttemptedOperations field for diagnostic purposes.
  • [SQL] SQL value queries (e.g. from e in Entity.Query select e.IntegerProp) can now be used with .Distinct().
  • [WPF] Create and Display screens' notification for VersionConflictException now contains the operations that were attempted.

v148.0.2

  • [WPF] Bugfix: ListController was not cloning changes made in its opened modal display screen back to its own context.

v148.0.1

  • [WPF] Bugfix: Reference and collection columns in lists were causing a memory leak.
  • [WPF] Bugfix: InlineReferenceView would set EntitySelector properties in the wrong order, leading to its Selection being cleared in some circumstances.
  • [WPF] Bugfix: Async loading of list cells used the buggy IsAsync WPF feature, which sometimes crashed. Now it uses a custom control, which doesn't.
  • [WPF] Bugfix: Right-clicking on a column header in a list screen could cause a binding error.

v148.0.0

  • [MODEL] The new model editor can now edit diagram numbers.

  • [MODEL] Association diagrams now have reasonable sizes out of the box.

  • [MODEL] Diagrams will now be generated into the Diagrams folder, like classes [used to/may once again be] in the Overrides folder.

  • [ORM] Bugfix: Reading of licence files was incorrectly requiring write permission and exclusive access.

  • [WPF] Removed The.WPF.Legacy.

  • [WPF] List overrides can now add custom screencommands to each row. These are exposed in the right-click context menu and as floating buttons at the end of the row.

  • [WPF] Many binding errors fixed:

    * Command binding in the default style for CommandButton was setting a fallback value of the string "Screen Command", which was not a valid value.
    * The default style for CommandButton was incorrectly expecting all CommandButtons to have data contexts with specific properties.
    * CommandGroupView was trying to set a MultiCommandButton's ItemTemplate property to "{Binding Name}".
    * A binding error was raised when a read-only MultilineValueView was displayed.
    * CreateView contained a vestigial reference to EntitySubtypeField, which caused a binding error.
    * LightboxView raised binding errors when told to display a modal screen with no preferred size.
    * A binding error would be raised if a tab was opened and then closed without switching to another tab first.
    * MultibarView and RemindersView's design-time data classes had missing properties, causing binding errors.
    * A data templating error was raised when using both a CreateModalController and a CreateController for the same entity type.
    
  • [WPF] Breaking: Removed SystemConverters.BooleanToClickModeConverter.

  • [WPF] Breaking: EntitySelector's SearchMode property is now an enum of type SearchMode.

  • [WPF] Breaking: EntitySelector no longer sets its own SearchMode.

  • [WPF] InlineReferenceFieldBase and subclasses now have an optional constructor parameter searchMode which will override the default search mode for the given relationship and choices set.

v147.0.1

  • Bugfix: If no license file was present, this was causing an error at startup. It should only cause an error later on when you try to read/write data.

v147.0.0

  • Removed support for .NET 4.5.2. 4.6.1 is now the minimum when running on the desktop framework.
  • Removed VS2012 and VS2013 support in The.Extension - 2015 only.
  • Removed support for Model.xml format and its editor, "Class Explorer".
  • Removed .theModel version 2 and support for the old event versions therein.
  • Removed VB.NET output from The.WPF templates.
  • Removed the requirement to use an actual file for .theLicence - any stream will do.

v146.0.1

  • [SQL] Bugfix: An InvalidCastException was incorrectly being thrown when a scalar query that returned nulls was executed.

v146.0.0

  • [ORM] Added a DynamicSequenceQuery read operation to support .Select(e => e.X) where X is a scalar value instead of an entity.

  • [ORM] The IRowSet abstraction has been removed to simplify entitystores and make them more composable. It's replaced with FreezeQuery and SelectByFrozenQuery operations, which work on an opaque key set by the entitystore; in the case of SQL Server this will be the name of a query-set table, in the case of RemoteEntityStore it's passed through, DataContractEntityStore uses a dictionary. This also reduces the amount of roundtrips required, as counts come back along with queries.

    The only thing we lose out on is this: previously, IEntitySets would hold strong references to IRowSets, which would then live exactly as long as the using code. That meant, in theory, automatic resource management. In practice, that abstraction was broken by SQLEntityStore's query/stability optimisation which saves the results into a table - this necessitated the introduction of a "garbage collecting" script. Further, it could never have worked over serialisation. We can now do better: FrozenQuerySet implements a finalizer which will usually send a ThawFrozenQuery operation at appropriate times, notifying the underlying entitystore (via proxy or otherwise) that it can drop the unmanaged resource. This will leak in the case of e.g. crashes, so we still need the GC sqljob, but it should be able to run far less frequently. For now, referencedata caching is less capable, since it doesn't have set objects to operate on - but the performance improvements elsewhere have cancelled it out. We may be able to reintroduce caching keyed by page retrievals or whole-type or something, capturing the only patterns which were really useful anyway.

  • [SQL] The.SQL has been simplified to be more like a collection of plugins than a 'layer'. It no longer has IServices or requires a composition process. DatabaseManager has been replaced with extension methods on IDatabase, and SQLEntityStore/SQLDocumentStore can be constructed with new(). For convenient provision of IDatabases, The.SQL.DatabaseFactory can optionally be used to do the higher-level decorator composition that Builder used to perform.

  • [SQL] The slowest part of overall application startup was SQLEntityStore creation performance, due to its runtime filtering of legacy-mode metadata. This has been moved to generated code. To be used with legacy-mode metadata, SQLEntityStore must now be given legacy generated persistence - this follows the same pattern as other modules, where instead of using My.Namespace.SQLPersistence.CreatePersisters() you write My.Namespace.Legacy.SQLPersistence.CreatePersisters().

  • [SQL] SQLEntityStore is now stateless - a long-running client can use multiple sql instances (for example because they connect to different load-balancing servers).

  • [SQL] Queries that return non-entity values (e.g. Human.Query(ctx).Select(h => h.Name)) can now be translated in some cases.

  • [WPF] Removed VirtualizingWrapPanel, which was too difficult to maintain. EnumSectionedCollectionField now uses a standard WrapPanel and is able to layout vertically instead of horizontally (meaning it scrolls horizontally rather than vertically). This approach has no UI virtualisation, but achieves acceptable performance by simplifying the contents of the panel - it should be ok up to 500~1000 checkboxes.

  • [WPF] Lightbox sizes, if customised by the user, will now be saved to preferences.

  • [WPF] IValueConverter names now have a consistent pattern.

  • [WPF] Improved textual summaries (which are used in subtitles)

  • [WPF] Improved Reminders sidebar aesthetics.

  • [WPF] Display screens' progress bar is now outside their scrollviewer and will not center itself offscreen.

  • [WPF] Bugfix: the Scale slider in the default shell was clamping to increments of 100%.

  • [WPF] Bugfix: EntitySelector was enumerating its Choices set even in search mode, leading to e.g. loading all Places into memory

v145.1.0

  • [MODEL] Added diagnostic code to property-order-within-section events to track down a potential bug leading to invalid states (THE-1053).

  • [MODEL] The editor will now validate identifiers and inform you if object names are not allowed.

  • [MODEL] Bugfix: When undoing an attribute's movement between sections, the editor didn't correctly restore its previous apparent ordering within the section.

  • [MODEL] Bugfix: Model editor crashed when processing events that cleared an entity's default sort. It doesn't generate these events itself but still needs to handle them.

  • [WEB] RemoteEntityStore now passes all test suites, and performance should be sufficient for testing/development. To activate features of The.Web we're using the ASP.NET Core conventions - you add services to its DI container in your Startup type's ConfigureServices() method, and then add middleware to its HTTP pipeline in the Configure() method. The.Web has a core service which makes the framework available to requests, a core middleware which provides its frontend code and API, and two dependent services/middlewares which add specific features. Using all available functions would look something like this:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTheFramework(Framework.Init())
              .AddTheProxyServer();
                .AddTheAdminSite();
    }
    public void Configure(IApplicationBuilder app)
    {
        app.UseTheFramework()
         .UseTheProxyServer()
           .UseTheAdminSite("/admin");
    }
    

    Generally you'd have other stuff in there like loggers, Add/UseMvc, etc. Check out Instagile/Internagile templates with the "Include Web Application" option for examples.

  • [WPF] In readonly Lists, which can be very large, cells containing lazy-loaded references are now asynchronous. This can improve responsiveness a lot if you have multiple relationship columns.

  • [WPF] Added a new mode of automated testing to The.WPF.Tests which lets us cover cases where the error occurs during styling + templating of FrameworkElements, including these two fixes:

  • [WPF] Bugfix: ImageControl was crashing when rendered.

  • [WPF] Bugfix: EntitySelector had no actual visual appearance.

v145.0.0

  • [EXPORT] RegisterExportFormats has been changed to AddExportFormats/ReplaceExportFormats, so it knows whether to replace or augment the existing set of formats.

  • [EXPORT] Bugfix: Excel export wasn't working with relationships and custom text formats (it had never been updated to use the newer APIs).

  • [ORM] Added IOwnedValue, which is a potentially-owned Value. Box<T> and Lens are non-owned IOwnedValue as well as IValue, so you can use them in any field.

  • [ORM] The mutable version of IEntitySet is now IOwnedSet (non-mutable ones are just IEntitySet). Like IOwnedValue, it potentially rather than definitely has an owner.

  • [ORM] PersistenceManager: Added "IEnumerable<Row> GetByQuery()" and "IRowSet SetFromQuery()", the dynamic duals of "IEnumerable<T> GetByQuery<T>()" and "IEntitySet<T> SetFromQuery<T>()".

  • [ORM] Replaced the SQL-specific optimisation for cheap GetAll() with a higher level optimisation which applies to all entitystores. IRowSets are now simpler and required only for queries; SetFromType has been replaced by CountType and SelectByType.

  • [ORM] RelationshipKernels now use a special directionless key structure internally, improving robustness when combining clones and partial reification. This fixes at least two bugs:

    • Viewing a list in a modal screen then cloning it back could lead to duplicate Creating/Loading kernelpairs, which affected Air Charter passenger lists.
    • Change description was capable of missing some relationship changes.
  • [ORM] Bugfix: We now support removing an element from a collection, saving the owning object, then putting the element back all in the same context - an edge case which had been broken basically forever.

  • [ORM] Bugfix: Calculated properties, even live ones, weren't being calculated on .ToString() until .Value had been called once. This was the root cause of failures to export/copy to clipboard.

  • [SQL] Bugfix: read-side transactionality wasn't working properly, but we didn't notice because we don't use it at the moment. (We will probably want to use it if we have a many-client distributed system).

  • [WPF] EnumSectionedCollection field, the one with the checkboxes, now has an "Invert Selection" command like the older control.

  • [WPF] FieldBase.ModelValue is now just FieldBase.Value. The name was a relic of when attribute fields were more complex.

  • [WPF] Removed Bound and Free variants of relationship fields; they use IOwnedValue/IOwnedSet instead.

  • [WPF] The Reminders ("Tasks") sidebar now has a user preference for whether to hide tasks without any work to do.

  • [WPF] The change confirmation dialog is now reusable and publicly available as The.WPF.Screens.ConfirmCloseController.

  • [WPF] Bugfix: If change-confirmation screens encounter errors loading the change list, those errors are now displayed, instead of leaving you with a screen alleging changes but refusing to expound.

  • [WPF] Bugfix: Closing display screens didn't work at all. They just stayed open and then crashed if you tried to crash them again.

  • [WPF] Bugfix: Rightclick->Copy Cell was failing in grids. Copy cell/row are now tested and programmatically available.

  • [WPF] Bugfix: Readonly EntitySelectors had a context menu which could be used to ILLICITLY clear their contents. This consequently affected LookupInlineReferenceFields.

  • [WPF] Bugfix: Sub-search fields now work even if you press enter/click ok very quickly.

v144.0.0

  • [ORM] EntityContext is now typed as IEntityContext in most places (for testability - the other concrete implementation is MockEntityContext).

  • [ORM] IImportPlugin is now IImportFormat, for consistency with IExportFormat.

  • [ORM] ExportManager is back, and now provides a way to discover IExportFormats, which can be registered at framework composition. There's no longer special WPF-level configuration for Excel export support, as this function is subsumed by ExportManager. ListController and similar features use all registered formats, so as well as adding Excel support this would let you add custom exports or remove the builtin CSV format. If you were previously using

    builder.WithExcelSupport(new ExcelExportFormat("template.xlsx"))
    

    then the new equivalent is builder.RegisterExportFormats(New CSVExportFormat(), new ExcelExportFormat("template.xlsx")) The actual ExportAsync function works with a new "PropertyPath" abstraction, used to describe and look up navigated/dotted entity bits; it uses the standard The.Utility.Status and so can be done in e.g. Progress screens. IAsyncScreenModel has been given a HandleProgress method as an alternative simpler form of reporting.

  • [ORM] The concepts of Lenses and Values have been combined. An IValue represents something which can be read, set and change-tracked; Lens is now a specific implementation of IValue. Others include Box and various Properties. Rule<T> and IValue<T> have .Convert<T,U,S> combinators which will produce wrapping converters - the optional S is for Traits, which can now override a function to statically provide custom conversions. ConversionManager.RegisterCustomConversion has been removed for now.

    Eventually, this work is intended to move 'modelled semantics' to a lower layer - functions like validation and criteria which are currently UI-dependent will be accessible from other UIs and potentially from business logic code (which currently has 'storage semantics' only).

  • [ORM] IEntityStore changes: The DynamicQuery readop no longer has a TypeName field.

  • [ORM] New backend: The.Persistence.Remote.RemoteEntityStore. This IEntityStore connects through an IEndpoint, either directly to another entitystore (LocalEndpoint) or indirectly over e.g. a web API (WebEndpoint).

  • [SEC] IEntityStore now receives a validated subject when executing writes - it isn't the responsibility of individual entity stores to determine the current user for audit records.

  • [SEC] Persistence, security and licensing now have shared responsibility for a single store-access path - as well as the current license checking, this will be where 'backend' security enforcement is done. See the doc comments or talk to me offline for more information on the productionisation design.

  • [SQL] SQLEntityStore no longer requires an IAuthentication for auditing RegisterQueryAuthentication() has been removed. See the security changes above for more info.

  • [SQL] For now (?) it's not possible to disable auditing - previously you could do this by NOT registering an IAuthentication, which was a common mistake.

  • [WEB] Major build changes, including the removal of npm and alterations to the structure of project files. I suggest a clean clone/checkout rather than trying to pull in-place.

    The new frontend build requires TypeScript 2.0 - you can get it from https://blogs.msdn.microsoft.com/typescript/2016/09/22/announcing-typescript-2-0/

  • [WEB] The.Web functionality is now split into multiple middlewares - IApplicationBuilder.UseTheAdminSite() for an actual web interface, and IApplicationBuilder.UseThePersistenceEndpoint() for a RemoteEntityStore-compatible proxy. Neither is production-ready yet - when they are there will be Instagile templates.

  • [WPF] The ValueField hierarchy has been collapsed into one simpler type. TModel and TView type parameters have been combined; instead of doing type conversion itself, it wraps an IValue, which may implement conversion internally, and may itself be converted using IFieldModel<T>.Convert<U>. That probably doesn't SOUND simple but the internals are a lot better - and you can apply the same techniques to any fields, reducing proliferation.

    FieldModelFactory does even less stuff than before. Someday it may go away entirely - for now its remaining purpose is to be able to create fields "in the same way that an attribute would", when it isn't obvious what traits to pick manually.

  • [WPF] A bunch more types have been moved to new namespaces, mostly going from The.WPF.Models/Views/Controllers to The.WPF.Screens/Fields/Sections. In general the goal is consistency, organising by component instead of MVC role, and making it clear which objects even have or don't have controllers.

    Some objects have been renamed or removed entirely - all the same functionality is there with the same top-level names, but the internals have been heavily refactored.

  • [WPF] Built-in converters were previously available by loading a ResourceDictionary, Resources.xaml - this led to many copies of the same dictionary in memory and a need to memorise string keys. Converters are now provided by members on a static class, analogous to SystemColors and SystemFonts.

  • [WPF] Mitigating the risk of all this restructuring, the WPF test suite has been greatly expanded. Most UI elements and concepts are now testable, and if we do find regressions we'll add tests for those as well.

  • [WPF] EntitySelector's SearchMode and SelectIcon dependency properties are now read-only and have a single source of truth.

  • [WPF] ScreenCommandFactory's overloads now have different names, for improved type inference.

  • [WPF] A number of accidentally-public types are now internal, improving obfuscation.

  • [WPF] Added ListController.ModalOpened lifecycle hook.

  • [WPF] Added DisplayController.ConfirmDiscardChanges utility method.

  • [WPF] Bugfix: InlineReferenceFields could sometimes set their internal EntitySelector's SelectIcon to the wrong icon.

v143.0.2

  • [MODEL] Bugfix: The optimiser can now combine the new event types.
  • [WPF] Bugfix: Wizard screens' Next and Cancel buttons were incorrectly both marked as the default button for the screen.
  • [WPF] Bugfix: The reminders sidebar would constantly update all reminders rendering it nearly impossible to use and consuming a lot of CPU.
  • [WPF] Bugfix: v143.0.0 accidentally reintroduced the incorrect call to HandleErrors in EntitySelector.
  • [WPF] Clicking in the textbox-like part of a search-mode EntitySelector will now trigger its search.

v143.0.0

  • This release requires an extension update. The previous extension version had a bug, erroneously reporting its version number as 141 instead of 142 - this one should update correctly from whichever you have.

  • [LICENSING] The.Reports is now obfuscated.

  • [LICENSING] Unit test runner processes are no longer exempted from licensing - detecting them was a potential hole in the system.

  • [MODEL] Model snapshotting has been reimplemented to use internal immutability. Snapshot cloning is gone and builders are no longer private; ordering is now stable and performance is vastly improved. The metamodel has also been simplified a bit, removing the distinction between RelationshipSide and RelationshipSide.Key.

  • [MODEL] ChangeEntitySection had a bug when PropertyOrder was set to a list containing two sides of the same relationship. This would produce unpredictable results, as there was no way to tell which side should go first. The new event ChangeEntitySectionV4 allows more specified ordering.

  • [MODEL] Stem optimisation is now fast and bug-free enough to run on entire models rather than just a 'minimal stem' which the editor has been assembling. It's now used in legacy model migration, reducing Common.Generated.theModel to 1416KB. (The original Model.xml is 2064KB and the .theModel originally in the shobiz repo was 2968KB.)

    That 1416 would actually be 816KB without all the HOBS tags - maybe we need a more efficient format for mass tagging?

  • [MODEL] New event ChangeEntityV2 - allows default-sorting by relationships as well as attributes.

  • [MODEL] Clicking on labels or doc sections in the labels now activates their associated controls.

  • [MODEL] The editor can now display basic model statistics.

  • [ORM] Bugfix: Assigning null to nullable string attributes with a maximum length would throw a null reference exception.

  • [WPF] Wizards have moved to The.WPF.Wizards. ('actual wizards' were already here, but now the screen is also). DisplayModal() on a wizard controller no longer blocks-then-awaits, which should make them more composable with other UI (and more testable). IWizard<T> now exists as a full-control alternative to WizardBase<T>.

  • [WPF] Sidebars have moved to The.WPF.Sidebars and have been simplified. The conflation between sidebars and screens has been cleared up; ISidebarModel is no longer a subtype of IScreenModel, and sidebars don't need ISurfaces. A general abstraction for 'locate some UI here' could be useful but that's not what we had.

  • [WPF] Criterion<T> now implements ICriterion<T>; combinators therefore now work on RelatedCriteriaFactories.

  • [WPF] Bugfix: There was a stack overflow in MultibarModel.Title.

v142.0.3

  • [WPF] All sidebars are now detached during The.WPF.Composition.Root.Dispose, rather than in TabbedShell.OnWindowClosing as before.
  • [WPF] Bugfix: EntitySelector was incorrectly calling HandleErrors instead of HandleErrorsAsync, and the compiler failed to point this out for some reason.

v142.0.2

  • [WPF] Duplicate captions are now supported in list screens and search screens.

v142.0.1

  • [ORM] Licensing is now skipped when running under xunit.console (as it is for other unit test runners).
  • [WPF] Bugfix: generated top-level menu buttons were all linking to the same screen, so you couldn't have more than one of them open at a time!

v142.0.0

  • [MODEL] Fixed incorrect dependencies for The.Model.Editor.nupkg.
  • [ORM] Removed obsolete service IDocumentStore.FindImageThumbnail.
  • [WPF] Renamespacing: IScreen has been renamed to ISurface, and IModel has been moved to namespace The.WPF. Some fields and screens have begun moving to their new homes (watch out for doublewides on the freeway).
  • [WPF] The role of FieldModelFactory has been reduced. It no longer has the general Create() methods which operate on an abstract attribute/relationship and return IFieldModel (as opposed to IFieldModel<T>), and it no longer has factory methods for a subset of random specialised field types. It's basically there for the use of generated controllers and criteria, to reduce the complexity of their templates.
  • [WPF] It's now safe to call TemplateManager.RegisterDataTemplate<TModel,TView> more than once for the same type arguments. This API is usually used through mechanisms like CustomControllerBase<TModel,TView>; in those cases, you can now safely inherit from them without using artificial generic types to force uniqueness.
  • [WPF] Create and CreateModal screens no longer support inheritance. Consequently, they now have more init options.

v141.2.1

  • [REPORTS] The dual-tfm nupkg was causing odd downstream build problems when doing MVC's equivalent of ngen. Its dependencies have been simplified to prevent this.

v141.2.0

  • [WPF] Added BoundSuggestionField.

v141.1.1

  • Obfuscation bugfix.

v141.1.0

  • [EXTENSION] Removed the project templates. Instagile (and Internagile) serve this purpose better, and the way we were building templates for the extension was awkward/difficult to maintain.

  • [MODEL] Bugfix: The optimiser can now combine the new event types.

  • [MODEL] Bugfix: The optimiser would sometimes reorder events so that change events appeared before related create events which could create invalid models.

  • [MODEL] Bugfix: In some circumstances, derived relationship captions didn't respect captions of their related entities. For example, ConstructionPeriod.Inventory in shobiz had a calculated display label of "Inventory" instead of "Custodian Detail".

  • [ORM] Persistence logging was broken and is now fixed.

  • [ORM] Clone logging was even more broken, in that it was actually removed on purpose some time ago - but the option still existed. It's gone.

  • [ORM] We now have tests for whether logging is working.

  • [REPORTS] The.Reports now supports .NET Standard 1.5. This isn't immediately useful, as the first desktop version of .NET which implements netstandard15 is 4.6.2 - but it now also works on Core CLR, UWP, Xamarin, etc. Hopefully we can update more packages to be cross-platform over time.

  • [WPF] The.WPF can now run in "headless" mode, allowing multiple instances per process. This mode can't display actual UI but services, controllers and viewmodels work as usual; views and controls work as long as you don't try to instantiate their visual trees into a Window (so: use a mock IScreen).

    The.WPF.IServices.Dispatcher is a Dispatcher subtype which will be either global or non-global depending on headlessness; use it instead of Application.Current.Dispatcher to get the usual thread synchronisation semantics while allowing your code to run in unit tests or advanced generation scenarios. The normal rules still apply - whatever thread you create The.WPF on becomes the 'main thread', so Display calls and SetViewFromModel calls and similar which use that services instance must take place on that same thread. However, different headless instances can choose to share threads or use their own.

  • [WPF] We'll be moving to a new namespace structure - vaguely speaking, instead of The.WPF.Controllers.Screens.Display we'll have The.WPF.Screens.DisplayController. Rather than try and do this all upfront I've moved existing code to The.WPF.Legacy, hopefully a familiar concept by now; new components are being built in the new structure and eventually old things will be moved.

    To maintain backwards compatibility (particularly for XAML namespaces), The.WPF and The.WPF.Legacy are ilmerged into a single dll. Cave canem.

  • [WPF] Command button groups are now enabled if any of their commands are both visible and enabled, and disabled otherwise.

  • [WPF] TDI shell's menu bar will now be disabled if a global modal screen is open.

  • [WPF] New SuggestionBox control and SuggestionField field. They provide text editing with the ability to search through and pick from supplied/generated suggestions.

  • [WPF] Minishell bugfix: IScreen.Services wasn't being set, due to case-insensitivity.

v141.0.0

  • This release requires an extension update.
  • All projects are now incremental-safe (meaning that msbuild will skip them if they do not need to be built).
  • [MODEL] .theModel deserialisation now enforces requiredness of event properties. It was not possible to construct an event in code with a missing required property, but previously you could create hand-written XML which would leave out these properties, causing them to default.
  • [MODEL] New representation of ordering: entities now contain a list of section ids, and sections have a list of property ids. Adding and deleting sections/properties still implicitly reorders, but moving them sets a current order instead of using index-based changes; this should allow for a considerably more stable editing experience. This change adds event types CreateEntitySectionV3, ChangeEntitySectionV3, CreateAttributeV4, ChangeAttributeV5 and ChangeRelationshipSideV5.
  • [MODEL] New CreateRelationshipV3 event, which is unnecessary but slightly more convenient.
  • [MODEL] New .theModel version 3, which removes the deprecated events and uses standard Guid serialisation instead of base64. Both v2 and v3 files will be supported for a period; v2 models will automatically be updated to v3 on save.
  • [MODEL] The model editor is now testable, which should help us achieve robustness.
  • [MODEL] Bugfix: DeleteRelationshipV1 didn't fully purge the snapshot, preventing you from later creating a similar relationship.
  • [ORM] Breaking: The static Conversion class has been replaced with a ConversionManager service. Registered custom conversions are now scoped to a framework instance like everything else. UICulture is now available from this service instead of the root.
  • [ORM] Bugfix: Reference properties now implement partial reification for remote loads, restoring HasChanges() correctness for non-navigable non-collection relationshipsides.
  • [WPF] Breaking: Added a new IShell - Shell.SWI.Minishell. This shell hosts a single modal controller and then exits, allowing the creation of wizard-based applications. The shell implementation has also been refactored to ease development of additional shells with shared components (hence the breaking change).
  • [WPF] Breaking: TemplateManager.RegisterCoreTemplates has been removed (or rather, made internal). This is now done automatically during Composition.Root.Build().
  • [WPF] Breaking: DeferredMenuBuilder is now reusable. (That is: you can build its menu more than once, for example in order to apply different permissions).
  • [WPF] Breaking: ControllerBase.OnModelCreated is now OnOpened and there is a new Opened event. OnClosed will only be called (and Closed raised) if OnOpened was called.
  • [WPF] Bugfix: NotificationObject.ExtractPropertyPath was failing with multi-segment lambdas created by C#, which use a MemberExpression of anonymous DeclaringType.

v140.3.1

  • Better IProgress for CopySchema.

v140.3.0

  • [IMPORT] Added NoImportPlugin implementation for IImportPlugin.
  • [MODEL] Some snapshot operations now support IProgress.

v140.2.1

  • [WPF] Fixed wizard content height bug.

v140.2.0

  • [ORM] New licence file version. .theLicence V2 has a human-readable grant and uses SHA instead of MD5 for entry-assembly hashes.
  • [WPF] Instead of a basically pointless generated menu template, TabbedShell now gives you a default menu if instead of your own IMenuBuilder you give it entity metadata. Like the template we used to have, it contains non-reference-data as top level search screens and a separate reference data access button. You can call it explicitly via MenuBuilder.Default.
  • [WPF] TabbedShell's LightboxView now wraps a ModalScreenView which just has the screen presentation sans overlay or resizing logic. This can be used externally as a component of similar UI.

v140.1.0

  • [WPF] ModalControllerBase has a new overridable OnDisplayed method, which is called just after the model has been pushed to the screen.
  • [WPF] EntityLink's default template no longer changes its contained Hyperlink's text properties (Foreground, etc.). These should now be controlled with Hyperlink styles rather than with EntityLink styles.
  • [WPF] EntitySelector will now disable its contained EntityLink when no entity is selected.
  • [WPF] EntitySelector's dropdown will now be shown or hidden when its textbox-like part is clicked, if it's not in search mode.
  • [WPF] The two ComboBoxes in advanced criteria now have locally-defined MinWidths, which are not be sensitive to styling.
  • [WPF] Fields in advanced criteria now have a MaxWidth of 600.

v140.0.0

  • [MODEL] Custom entity and relationship captions are no longer automatically uncameled. This might change some default section names.
  • [MODEL] The generated shallow-copy method is no longer virtual, so you cannot extend it for any entities.
  • [MODEL] The static Specify method for entities has been moved to the Specifications template, which is now optional.
  • [WPF] The generated menu no longer uncamels entity captions - they should have already been customised or automatically uncameled.

v139.1.0

  • Reduced The.Extension dependencies to a comprehensible level (down from 29 to 5)
  • Web projects no longer trigger rebuilds of the solution.
  • Some test code is now using xUnit instead of MSTest. This doesn't add any features (apart from tests running a little faster) but it means we can run 'test suites' for plugin implementations, e.g. the upcoming RemoteEntityStore.
  • [ORM] "Partial reificiation" has been extended. Relationships now track changes made when their OtherSide IsPresent, without wiping out those changes if they later EnsurePresent. Entity HasChanges and collection Count should return correct values for partially reified and even non-navigable relationships.
  • [ORM] DataContract persistence now has support for queries over IEntity. (e.g. if you just want to search by .Kernel.modifiedOn or something). This already worked in SQL.
  • [WPF] EnumSectionedCollectionField now scrolls to the top if the filter text changes.

v139.0.0

  • [ORM] The generated shallow-copy method is now virtual, so you can extend it for specific entities.

  • [ORM] ImportManager.CopyData and ImportManager.CalculateProperties are now cancellable via token.

  • [REPORTS] Updated to a new version of Roslyn which will hopefully fix compiler warnings about crashing analysers.

  • [SQL] Bugfix: the SQL Agent job which cleans up query tables wasn't correctly configured to run a multi-step job, so if you had more than one framework database on the same SQL Server instance only the first would have its q tables cleared.

  • [WPF] New feature: Wizards. Implement wizards as subclasses of The.WPF.Wizards.WizardBase<T> and display them using a WizardModalController. A wizard is defined by a Run method containing calls to await host.ShowPage() (and similar methods) which define the wizard UI. Arbitrary control flow can be used as long as the function is deterministic; the wizard object itself is the viewmodel and can contain state. Sample code:

    protected override async `Task<int>` Run(IWizardHost host)
    {
      await host.ShowPage(new SelectValuePage(), () `=>` SelectedValue `>=` 0); // optional validation function
      if (SelectedValue `>` 5)
      {
      	await host.ShowPage(new ConfirmHighValuePage(), "Check Number"); // optional title override
      }
      return SelectedValue;
    }
    
  • [WPF] New sidebar: Reminders. This is the extracted version of the shobiz 'Tasks' feature; Task was too overloaded a term to use. To create a useful task list, supply The.Search.Reminder<T> objects or IReminder implementations, which define a search and some options for security, display, etc.

  • [WPF] ListController has new lifecycle hooks and corresponding events: OnModelOpening(), OnModalClosed() and OnModelCancelled().

  • [WPF] Convenience/safety function on DisplayController<T> - Task<T> GetEntity(), which waits for loading if any is happening and then (or immediately) returns the loaded entity.

  • [WPF] ProgressModalController now supports true cancellation; it passes CancellationTokens to its monitored work functions and signals them as necessary.

  • [WPF] Added IController.Close() - this lets you close a screen controller early, even if its IScreen is still present in the shell, which can be used as a performance optimisation to throw away previously used stuff. Closed screens can also be re-opened; you could de-Embed something and Display it instead, for example.

  • [WPF] Convenience .Screen property on ControllerBase.

  • [WPF] Lots of small consistency and appearance improvements to the Criteria screen.

  • [WPF] NASA dates now support a 'W' modifier to step forward or back by a number of weeks.

  • [WPF] Making matters worse, BoundValueSectionedCollectionField is now virtual.

v138.0.0

  • Added unit tests for The.Web, using the new "mstest 2.0" - let me know if you experience any problems there.
  • Running the Access tests now requires the 64-bit redistributable because mstest v2 isn't a big fan of 32-bit. There's a copy at \acdc\AgileTools\Microsoft\AccessDatabaseEngine_X64.exe
  • The.SQL.nupkg now contains an extra dll. Beware the ides of Update-Package!
  • [IMPORT] CSVImportPlugin now optionally treats white space as null, this is enabled by default.
  • [IMPORT] The executor will no longer try to extract data consisting of only nulls. With the above change, this should get rid of extracted entities with blank names from CSV.
  • [MODEL] The structure and implementation of the TemplateRunner api, which loads and processes code-generators based on the entity model, is now less crap.
  • [ORM] Breaking: FileLogger.TryCreate's meaningless 'linesOfStackTrace' parameter has been removed.
  • [ORM] FileLogger now always writes entries in the order they were logged, using a long-running background thread.
  • [ORM] The.Composition.Builder will now register the provided logger as a disposable if it is one. This may break consumers who were using the same logger instance with multiple Root instances; preference store disposal has the same problem.
  • [ORM] Moved EnvironmentManager up to The.WPF - it didn't really make sense as a core service, because it's fundamentally callback-driven rather than transactional.
  • [SQL] The IDatabase abstraction (The.SQL.Client) is now server-agnostic; it works with all ADO.NET providers, not just MS SQL Server.
  • [WPF] Added IServices.EnvironmentManager (see above).

v137.4.3

  • [WPF] No longer immediately crashes at startup.

v137.4.2

  • [WPF] LightboxView now respects IScreenModel.AreCommandsEnabled, but for real.

v137.4.1

  • [WPF] Fixed some memory leaks - MultilineTextBox was adding a DependencyProperty change watcher without removing it, and ContentScreen.xaml was binding to the .Count property of a List (which uses a ReflectPropertyDescriptor, which WPF leaks).
  • [WPF] LightboxView now respects IScreenModel.AreCommandsEnabled.

v137.4.0

  • [ORM] The Metadata field on RelationshipBase is now a property, for convenience of binding; similarly, the fields on PropertyInfo/AttributeInfo/RelationshipInfo have become properties.

v137.3.0

  • [WPF] ContentScreen dynamic implementation improved - it can now look up sections as well as fields.

v137.2.2

  • [MODEL] Legacy model support and migration has moved to The.Extension. TemplateRunner no longer does this conversion, and The.Model.Legacy.dll is no longer included in packages. This is a step towards removing Model.xml, which only SHOBiz still uses.

v137.2.1

  • [WPF] Bugfix: The weak event handler that was propagating events from ListRowBase.PropertyChanged to VirtualisedSet.ItemChanged was being garbage collected too early. (!)

v137.2.0

  • [WPF] Fixed a missing null check in ListRowBase.HasChanges.
  • [WPF] CollectionSelectors no longer depend on MultilineTextBox to draw their border, similar to MultilineFields.
  • [WPF] Bugfix: Some relationship fields never raised IsValid or raised it incorrectly in a way that could cause a loop in validation if there were dependent validation rules on other affected fields.

v137.1.1

  • [WPF] MultilineFields no longer depend on MultilineTextBox to draw their border, so it's safe to have a borderless trigger (as shobiz does). In future we should encapsulate "box + some inline buttons" into a control which can be themed.

v137.1.0

  • New package: The.Web. This library can be used by ASP.NET websites to display a basic data-browsing SPA. It's not useful yet, but will be expanded over time.
  • New test project The.Test.Site. This application loads The.Web in a special development mode where its frontend code is hot-reloaded as changes are made.
  • [WPF] Sectioned collection fields didn't support IFieldModel editability control - .Immutable() and FieldControl.IsEditable had no effect if you'd specified rowsEditable or listEditable true in the constructor. Now it works.

v137.0.3

  • [ORM] Data import now supports multiple lookup extracts into one target table/column from two or more source table/columns.

v137.0.2

  • [ORM] Bugfix: PipelineBuilder would throw an exception if given a model with a DeleteAttributeEvent that didn't refer to an attribute being imported.

v137.0.1

  • [ORM] POCO queries now support Enumerable.Empty<T> where T : IEntity

  • [ORM] POCO queries now support the use of nested generics without casting - for example, Func<Model.T, IEnumerable<Model.U>> will be translated to Func<Model.DataContracts.T, IEnumerable<Model.DataContracts.U>>. In particular, this means that SelectMany(e => e.Collection) works from C# - previously it only worked from VB which inserted an implicit cast into the expression tree.

  • [ORM] Data import now supports deleting imported model elements.

  • [SQL] SQL queries now support ternaries - x?y:z or If(x,y,z). Example:

    Place.Query().Where(p `=>` p.Foo == (p.Bar `< 3) ? (p.Baz) : (5))`
    
  • [WPF] Selectors now always use GetByID rather than Clone. It's currently too difficult to detect when using clone would overwrite innocent bystander data in the target context.

v137.0.0

  • Removed The.Framework.Legacy
  • [ORM] Builder.Configure() is now Builder.Build().
  • [ORM] IEntity has a new ID property, because I did a mental huffman encoding of the codebase and the single most common element was ".Kernel.ID".
  • [ORM] Bugfix: FileLogger was writing UNIX linebreaks instead of Windows ones.
  • [SQL] Builder.Configure() is now Builder.Build().
  • [WPF] Builder.Configure() is now Builder.Build().
  • [WPF] ValueSectionedReferenceFields no longer create references in the database! We've decided that actually it's not ok for other controls (selectors) to require persistence.
  • [WPF] Selectors now use GetByID rather than Clone when necessary in order to avoid clobbering objects already in the target context. It won't actually perform an extra DB hit, since the value will be fetched out of the EntityContext.
  • [WPF] Content screen have a new option: IncludeOnlySections. This can be used to create content controllers with subsets of their usual UI.
  • [WPF] SectionControl now correctly stretches out its content internally; the Inky theme was working around this, but it meant apps with custom themes would get the wrong behaviour.

v136.3.1

  • Bugfix: objects loaded by OnSaving would not have their non-live calculated properties re-calculated during the same save.

v136.3.0

  • [ORM] Entity subclasses can now override OnSaved to be notified once they've been updated in the datastore and are safe to further modify or access.
  • [WPF] Subclasses of controllers with ____Options types (Content, Display, List) can now access the provided parameters via a protected field.

v136.2.0

  • [MODEL] Bugfix: Events with list parameters would never evaluate as equal.
  • [MODEL] Bugfix: ModelSnapshot.Clone would clone one of its collections of relationships but not the other, causing the cloned model to have two copies of each relationship.
  • [MODEL] Bugfix: CopyAttributesV1 events would immediately be optimized away after being generated.
  • [WPF] ValueSectionedReferenceFields now create references in the database, so that other controls that expect the entity to exist in the database don't get confused.
  • [WPF] The EntityLink on ValueSectionedReferenceField is now enabled.
  • [WPF] IScreenCommand.Name is no longer readonly.
  • [WPF] FieldSection subtitles no longer become multiline.

v136.1.1

  • [WPF] Properly centered lightbox titles and removed some of their excessive padding.

v136.1.0

  • [ORM] Conversion now supports date/datetime -> string.
  • [SQL] Bugfix: Queries with conditions containing values reached via relationships could generate unqualified column references.
  • [WPF] IFieldModel has a new property to allow section summaries to be constructed. Default summaries have changed from labels to content
  • [WPF] Bugfix: valuefields not bound to attributes weren't updating their view if IFieldModel.Value was set.

v136.0.0

  • [ORM] ImagePresenter.AdjustAspectRatio and .CreateThumbnailAsync can now work with image sizes that are specified in only one dimension; this will allow them to produce sizes arbitrarily large in the other dimension to maintain aspect ratio.
  • [WPF] Bugfix: List columns displayed using fields would bind directly to the field and not to its Content property. This broke lazy data templating and wrapped fields.
  • [WPF] There is a new MultiCommandButton control, which allows functionality like TDI shell's CommandGroup to be used in other contexts.
  • [WPF] ImageControl no longer has context menu items to rotate the displayed image.
  • [WPF] Bugfix: The second specific type of ProgressModalController<T> displayed would try to register the same data template already registered by the first type, leading to an error being raised.
  • [WPF] Breaking: ProgressModalController has a new constructor parameter that can be set to True to cause the modal dialog to have no OK button and automatically close when the monitored function completes. Setting the parameter to False preserves current behaviour.
  • [WPF] ImageControl now has its default action (invoked by left-clicking on the image) first in its context menu instead of last.
  • [WPF] The new ImagePresenterExtensions module in The.WPF.Utility can be used to perform the operations in ImageControl's context menu.
  • [WPF] Breaking: ImageField is significantly redesigned and is now named SectionedImageField.
  • [WPF] Added a new ISidebarController: Multibar, which presents multiple other sidebars as collapsible sections.

v135.1.0

  • [ORM] Refactored relationship initialisation, fixing a couple of issues:

    * Unloaded references cloned into an empty context did not copy their lazy-load target
    * Non-navigability had some holes and didn't quite suppress all access to the relationship
    
  • [WPF] Removed [View] and [NoView], which were previously used for nominal templating.

v135.0.0

  • [MODEL] TemplateRunner can now be given a specific model file to work with rather than a directory in which it looks for a potential legacy import.
  • [MODEL] The.Utility.exe now has a "gen" command for running templates.
  • [MODEL] Fixed an error in the editor error handler which could unhandle the handled error.
  • [MODEL] Fixed an incredibly serious optimizer bug which could basically cause you to silently lose any work at any time (sorry).
  • [MODEL] Editor handling of multi-event undo was incorrect; it would run the event undos forwards, rather than backwards. This led to a failure when undoing composite operations like Extract.
  • [ORM] IEntityInfo has been revamped. Its relationship factory methods are gone (see The.Relationships.RelationshipFactory) and making entities has been cut down to a single call which wraps the constructor.
  • [ORM] EntityInfo<T> can now implement IEntityInfo without a generated subclass. Metadata.tt still generates them, but it's only for developers' type-safe metadata convenience.
  • [ORM] IEntityInfo.Visitor is now IVisitor, and the unused relationship versions have been removed (C# does not support nested interfaces).
  • [ORM] Runtime PropertyInfo now has an IsLegacy flag for use with the legacy-mode ORM.
  • [ORM] OrderByProperty and ThenByProperty extension methods on IQueryable<T> to efficiently sort queryables (once the query is executed) using SetOrderings.
  • [ORM] Bugfix: It is now actually possible to have a attribute of type nullable long.
  • [ORM] Bugfix: Setting ForceInline on ListOptions would not actually force a list to be inline or non-inline.
  • [WPF] TemplateManager is no longer partly static, and the obsolete method RegisterNominalTemplates has been removed.
  • [WPF] Bugfix: the context menus for datagrid columns were partly broken ('Remove column' for example).
  • [WPF] Tabs which failed to fully load due to a failed viewmodel creation can now be closed.
  • [WPF] Lightboxes without explicitly-set minwidth/minheight on their views will now shrink as necessary if the screen is constrained in resolution.
  • [WPF] Improved ProgressModalController a little - it uses a scrollbar, and it can handle UI-bound work now (previously this would lock up!).
  • [WPF] List field caption comparisons are case-sensitive once again (not that there's any particular benefit to it, but it's consistent with property name comparisons elsewhere).
  • [WPF] FieldSections with more than one field now have a default subtitle listing their contents.
  • [WPF] It's no longer necessary to explicitly reference the shell Resources.xaml to get lightbox sizing working.

v134.1.1

  • [ORM] The .Parent and .Metadata fields on attributes and relationships have been changed to properties, allowing them to be used as data-binding sources in WPF.
  • [ORM] Bugfix: When using VB.NET output, all relationships were marked AdminOnly and did not show up in lists.
  • [WPF] Overriding InitialiseModel() on ControllerBase and ModalControllerBase subclasses is no longer required. It's still permitted, just not required.

v134.1.0

  • [SQL] CreateTriggers now sets up a SQL Agent job which purges the 'q*' temp tables used for query set caching. By default, this job runs once every 6 hours. If there are multiple framework databases on the same SQL Server instance, they share a job schedule and use one job step per DB.

  • [WPF] Added IntegerToCountingStringConverter, which uses NLP to pluralise things only if there is more or less than 1. Example of use:

      <Run Text="{Binding Collection.Count,RelativeSource,Converter={StaticResource TheIntegerToCountingStringConverter},ConverterParameter=item}"/>
    

    This produces either "1 item" or "2 items" etc.

  • [WPF] EntityLink now supports the TextDecorations property.

v134.0.0

  • [ORM] The internals of The.Search have moved around a lot, but it's unlikely to break any client code in practice.

  • [ORM] Reports (the generated classes accessible via Businessclass.report) now have .Services available.

  • [WPF] The lightbox change in 133 was a bit half-baked and they grew too easily. Instead of trying to autosize, lightboxes now specifically respect their contained view's settings:

    If nothing is set on the view, the lightbox will have a theme-defined starting size (keys in The.WPF.Shell.Resources) and can grow up to the screen size (with a border).
    If Width/Height is set the lightbox will have that starting size (and minimum size will be adjusted if necessary).
    If MinWidth/Height is set the lightbox will be able to shrink to that size rather than its default.
    If MaxWidth/Height is set the lightbox's resizing will be constrained.
    

    This replaces the semi-hidden widthoverride stuff that LightboxModel used to have, so it's a breaking change.

  • [WPF] New control, NotifyingContentPresenter - it's a subclass of ContentPresenter with a ContentChanged event raised when the visual children are altered.

  • [WPF] List field caption comparisons are no longer case-sensitive.

  • [WPF] ListController will now raise an error if multiple list fields (columns) are defined with the same caption.

  • [WPF] ErrorBorder is now a ContentControl subclass, allowing more powerful theming options.

  • [WPF] Minor bugfixes to error display.

  • [WPF] Fixed confirm-changes display (it wasn't showing up, with a hidden internal exception) and improved its UI a bit.

  • [WPF] Added a utility class, BindingErrorListener, for diagnosing errors - attach it to PresentationTraceSources, and it turns them into first-chance BindingExceptions. This can be enabled in an application using The.WPF.Builder.WithBindingExceptions(true). Consequently, I've fixed a number of long-standing binding errors.

  • [WPF] New attached property SectionControl.InSection - this will be true on xaml elements which are within a section, and false outside.

v133.0.0

  • [MODEL] Fixed the Currency/MaxLength 'trap', which could get models into an uneditable state. The editor now tries pretty hard to prevent you setting maxlength on currency, but if you do it anyway it will just be ignored rather than rendering the model invalid.
  • [MODEL] Bugfix: when embedded in Visual Studio, the error wasn't reporting pending events as dirty. This meant that if you made a change then quickly closed the window, it might not get saved.
  • [ORM] QueryRowSet's temp-table mechanism now regenerates its temp table on demand if it's been cleaned up.
  • [WPF] Search screen optimisations: a search without any criteria uses the faster GetAll() rather than Query(). Criteria groups and tabs which were at one point 'activated' by entering some parameters can now become 'inactive' again, improving the performance of searches which have had many UI changes.
  • [WPF] Sub-search fields - e.g. the Classifications criterion on Incentives screen - now preserve the search parameters you've put into the screen between multiple visits. It can be cleared with the usual (X) button.
  • [WPF] ListController.Refresh is now publically available for embedding screens.
  • [WPF] DisplayController now has a DisplayOptions.

v131.0.0

  • Breaking: The.WPF.Export has become The.Export. WPF's ExportManager no longer exists; a module The.WPF.Controllers.ListExporter has the same functionality.
  • Extremely breaking: The.Persistence has been restructured, moving types out of the ReadOps and WriteOps modules into proper namespaces.
  • [ORM] PreferenceManager will now only flush the preference store the first time it is disposed of and will stop its scheduled flushing when disposed of.
  • [ORM] Bugfix: AppDataPreferenceStore was not safe against preferences being written or cleared while also being read or flushed.
  • [ORM] Bugfix(?): Sorting was wrong for most entities - it went by Text instead of modifiedOn. Reference data still uses Text.
  • [SQL] Rather than returning ID lists from the server to the client, queries now store them in temporary tables - enabling very large resultsets.
  • [WPF] TabbedShell is no longer considered to be the owner of its core services - they are injected into it rather than created by it. As such, it will no longer dispose of them and this must be handled by application code (the project templates already do this).
  • [WPF] Lightboxes now grow if their content specifies a Width/Height/MinWidth/MinHeight.
  • [WPF] There are now preferences for list sorting.
  • [WPF] ListOrdering now refers to a column's Caption instead of its DisplayIndex.
  • [WPF] Lists no longer need to re-apply sorting if a column is added or removed; they can be sorted by non-visible columns.
  • [WPF] Bugfix: ListSortingBehaviour was adding insted of removing an event handler when it was detached (which in practice was probably never).
  • [WPF] Bugfix: the UI virtualisation implemented by ListController and VirtualisedSet had a hole; if the datagrid was refreshed while it a selection, it would enumerate every item looking for the old selection.

v130.1.2

  • [MODEL] InvalidEventException was marked as Serializable but didn't have an appropriate constructor, which meant that model errors could bring down Visual Studio.
  • [MODEL] Compounding the above problem, parts of the template generation process did not have error handling and let the exception out into the world.
  • [MODEL] Added an "Edit Model" command to the extension, which finds your current .theModel and loads it.

v130.1.1

  • [IMPORT] Generated String attributes have a maxlength.

v130.1.0

  • [IMPORT] 'Spilled' attributes also won't be Display.List.

  • [WPF] Generated search criteria for Int, Long, Decimal and Currency now use a new kind of single-field range. You can enter a specification like

    4,6-8, 10-
    

    and it will return results where the value is 4, 6, 7, 8 or greater than 9.

v130.0.0

  • [SQL] Breaking: SQLDocumentStore now has a separate throttle for fetching metadata. The default limit is 20.

v129.0.1

  • [IMPORT] When using MaxAttributesPerSection, attributes that spill out of the main section won't be made search criteria by default.
  • [WPF] FieldHeader now has a max width by default. This means that really long criteria or property names don't break layouts.
  • [WPF] Criteria sections of search screens can now scroll vertically if necessary.

v129.0.0

  • This release requires an extension update.

  • [MODEL] AdminOnly is back for .theModel. This time it applies to relationshipsides as well as attributes; you can set it with CreateAttribute, ChangeAttribute or ChangeRelationshipSide events. The new flag is in the model editor, and Model.xml import will copy over the old flag.

  • [MODEL] New CopyAttributesV1 event allows modelling of moving data through relationships. This enables a new editor feature "Extract as reference data" - you can pick a property and turn it into an entity.

  • [MODEL] Improved the presentation of editor command errors.

  • [MODEL] Model-level tags are now visible in the right pane.

  • [ORM] The.Validation.IValidated<T>.Rule is now The.Validation.Rule<T> - delegates declared in interfaces are not super compatible with C#.

  • [ORM] Security now supports a notion of a user 'being an administrator' - part of the subject returned by IAuthentication implementations. This will be used with e.g. AdminOnly properties.

  • [ORM] CSVImportSource now detects invalid rows within an otherwise-valid CSV file and reports an error with debug information.

  • [ORM] Import now supports copying data between entities. This is used as an underlying primitive to replace the old higher level tag-based 'extract enum' feature.

  • [WPF] List screens in Inline mode now use ShowOnForm rather than ShowOnList to determine column visibility.

  • [WPF] The List.CreateAttributeField and CreateRelationshipField override points are now List.CreateField. It's also now provided with the list's viewmodel as an extra parameter, and can use it to make decisions or alter it based on the provided infos.

  • [WPF] List controllers now use a ListOptions. This has the editability/modal flags that were previously in the constructor, as well as two new settings:

    • bool AdminMode - if AdminMode is set and the user IsAdmin (as determined by SecurityManager), then they will be able to see or export AdminOnly properties.
    • bool? ForceInline - if set, this sets IsInline to true/false on the viewmodel, and can be used instead of overriding or embedding the list.
  • [WPF] Content screens now support AdminOnly in the same way as list screens - ContentOptions has an AdminMode parameter, and AdminOnly fields will be visible to IsAdmin users if it's true.

  • [WPF] Bugfix: FieldSection.IsValid was incorrectly always True before IsValid changed on any of its fields, regardless of their starting IsValid values.

  • [WPF] Bugfix: Fixed several problems with EnumSectionedCollectionField.

    • Scrollbar thumb would become very small when scrolling beyond the end of the collection.
    • Toggling a selection would scroll the view all the way back to the top of the collection.
    • Items that are too long to display completely are now trimmed with ellipses.
  • [WPF] Bugfix: Whole-section validation was not displaying if the section was wrapped using .Subtitled() or .Resizable() or what-have-you.

v128.2.0

  • [IMPORT] New configurable Structure property: MaxAttributesPerSection. If this is not null, attrs past the Nth will be put into new sections named 'Section 1', 'Section 2', etc. Instagile uses this for schema import.
  • [IMPORT] Relationship property names are now sanitised and disambiguated in the same way as attribute property names.
  • [IMPORT] Name sanitisation is now more robust.
  • [IMPORT] Made a start on heuristically detecting reference data types.
  • [MODEL] Editor-created attributes now default to nvarchar(255) instead of to int.

v128.1.2

  • [WPF] Bugfix: Single-section Content screens had their last field stretched, fallout from fixing sections in the opposite direction.

v128.1.1

  • [SQL] DDL templates were crashing when run on a model containing only one entity.

v128.1.0

  • [ORM] A framework instance can now report its own version number via IServices.Version.

v128.0.1

  • [IMPORT] New Structure config option for whether to generate IsLegacy attrs or just make them display=none.
  • [ORM] Added another piece of relationship change notification: EntityReferenceProperties now raise ValueChanged if a clone-back updated their current .Value.
  • [WPF] Inky theme bug: SectionControls didn't constrain their childrens' size.

v128.0.0

  • [MODEL] The delegates supplied to TemplateRunner now have nominal types for ease of use purposes.
  • [WPF] Breaking: Content controller CreateXSection functions are now public.

v127.3.0

  • [WPF] Content screen models now have another System.Dynamic feature - expando mode, you can add properties arbitrarily. We might consider adding this to other builtin screenmodels...

v127.2.1

  • [ORM] Bugfix: Saving an entity with two changed relationships to the same other entity no longer leaves one of those relationships kernels as having changes.

v127.2.0

  • [IMPORT] Added diagnostics for legacy and missing model elements.
  • [MODEL] Optional.If now has overloads which take Task, Task<T>, etc for use with async.
  • [OFFICE] ACE import now ignores temp tables.
  • [ORM] For some reason, IEntityInfo was exposing mutable dictionaries, as if you could modify its attributes.
  • [WPF] Global errors during global modals are now displayed attached to the global lightbox.

v127.1.1

  • [WPF] Command button groups are now disabled if any of their commands are disabled. To remove an option from the group, use IsVisible instead of IsEnabled.

v127.1.0

  • [IMPORT] CSVImportPlugin now supports specifying a list of files instead of a whole directory.

v127.0.0

  • Visual Studio 2012 is no longer supported. Let me know if you still need it for some reason.

  • New packages The.MSExcel (which will contain an IImportPlugin at some point) and The.Model.Editor.

  • Obfuscation has been added to The.Reports and The.Model.

  • [MODEL] New properties created by the editor now display on forms/lists/search by default, except for relationship sides with reference-data parents.

  • [ORM] Entity classes can now override OnCreating(). It works like OnSaving(), except, for creating, instead of saving.

  • [WPF] Excel export support has moved to, The.MSExcel. Apps which do not need excel support can now avoid the 2.5MB dll dependency. To add Excel export support to a The.WPF instance, use

    .WithExcelSupport(new The.MSExcel.ExcelExportFormat("template.xlsx"))
    
  • [WPF] Criteria expandedness on search screens is now preference-based.

  • [WPF] Inky theme visual consistency improvements.

  • [WPF] Sections containing unlabelled fields now allot those field contents their entire vertical space, rather than top-aligning them. This means that listboxes grow with the user-resized section, and custom UI can fill allocated space (such as the model editor!)

  • [WPF] Bugfix: BLOB property fields weren't working properly.

v126.0.1

  • [ORM] Bugfix: the reference data cache was ignoring navigability.

v126.0.0

  • [IMPORT] CopyData can now use a deployment data path different from the one used when CopySchema was run. Either specify an extra parameter to ImportManager.CopyData() or set .DataPath in an EditPipeline function.

  • [IMPORT] The default ShouldEnforceNonNullability in generated models is now false.

  • [MODEL] Fixed a model editor error which would occur when creating, renaming, then deleting an attribute or relationship.

  • [MODEL] The editor sidebars can now be shrunk to 0 width.

  • [MODEL] Overall model settings are now accessible in the top right, above the events pane. You can edit the name or, via a dialog box, flags.

  • [MODEL] Errors in editor commands are automatically trapped rather than being able to crash. This will be particularly useful when we start extending the commands in embedders.

  • [ORM] Even Persistent calculated properties no longer have changes when first created. Our contract previously was based on an inadequate implementation, not a useful design.

  • [ORM] Transient calculated attributes will never be calculated, even for the purpose of setting OriginalValue, until they are first explicitly called upon. This allows them to be an expensive calculation with an opt-in to the cost by business logic.

  • [ORM] CalculationMode.Persistent has been split into OnSave and OnSaveOrClone. In standard UI patterns, the difference is that OrClone stuff will be transferred between modal dialogs correctly (but expensively).

  • [ORM] The.WPF.Values has become The.Values. This poorly-named subsystem contains conversion and validation code for operating on primitive .NET types with optional framework-specific metadata (Traits). In future we'll be able to share this functionality between frontends, such as the hypothetical The.Web.

  • [ORM] IEntityStores are no longer required to supply counts or ids for non-navigable relationships. This allows us to optimise loading of e.g. reference data.

  • [ORM] Accessing the public API of nonnavigable relationships through .props will throw exceptions, as the data is no longer necessarily available.

  • [SQL] SQLReader no longer retrieves counts or ids for non-navigable relationships. This reduces costly index scans, particularly for reference data which may contain collections of entire other tables.

  • [WPF] Attribute fields are now 'lazy' about accessing their view data, so that you don't pay the cost of any property calculations until a field is displayed (for example, because you have a section closed).

  • [WPF] Collection fields have been extended to allow extra customisation. ValueSectionedCollectionFieldBase's constructor now has separate listEditable and rowsEditable parameters instead of one contentEditable parameter. listEditable governs the visibility of Create and Remove buttons and rowsEditable governs the editability of list rows.

    BoundValueSectionedCollectionField and FreeValueSectionedCollectionField have new constructors that pass the new ValueSectionedCollectionFieldBase parameters. The existing constructors remain for convenience and are now delegating; contentEditable will be passed to both new parameters. InlineCollectionFieldBase has a new generic overload that allows its view to be overridden, and the HasChanges property for the bound variant now correctly takes IsPresent into account.

  • [WPF] Search screens now have SearchOptions. The first new option is bool AutomaticRefresh, which is on by default; with this flag set, the search screen will re-perform its search if an entity of that type is saved by the local user.

  • [WPF] ValueField and FieldSection have been optimised to avoid loading model data when possible, which lets the user choose when to pay for calculated properties.

  • [WPF] SectionControls now display real/inner validation errors instead of just "has errors."

v125.0.0

  • This release requires an extension update.
  • [MODEL] New event: CopyForeignKeyV1. This event establishes a source of data for a relationship - attributes on either side are matched up to produce inserts. It's supported by an editor workflow command "Make Foreign Key" which transforms an attribute into a legacy datasource for a relationship. ForeignKeySnapshot objects can be used by templates and imports.
  • [MODEL] The editor now supports theming. When embedded in Visual Studio it will use the VS theme, and can be customised in other applications using an ITheme.
  • [MODEL] Tags and other immutable data (e.g. foreign keys) are now presented in a more compact form if they're known to the editor. For example, it knows about import table/column sources and will give you a tooltip instead of a K/V view. This design allows tags to be shown inline in property/entity lists.
  • [ORM] The.Import system has been refactored toward the goal of making data transformations modellable by the editor. Some of the tags are no longer needed, and the EditStructure api has been cut down, possibly towards zero. A number of data-import bugs have been fixed and performance is improved.
  • [ORM] The.Attributes.FileProperty.File and ImageProperty.Image are now The.Attributes.FilePresenter and ImagePresenter.
  • [ORM] MIME type handling has been centralised in The.Utility.MimeTypes.
  • [SQL] CreateTriggersWithoutAudit was broken - inserts still audited.
  • [WPF] Bugfix: Create screens would never show validation errors, even after the user attempted to save.
  • [WPF] Bugfix: Custom conversions registered with one overload of RegisterConversion would cause an EntryPointNotFoundException to be raised when conversion was triggered.
  • [WPF] Bugfix: Fixed crash when resetting link column in a list controller after sorting it.
  • [WPF] Bugfix: Double-click behaviour in lists now actually works properly. No longer will double-clicking on row headers or scroll bars open the selected row.
  • [WPF] IScreenModel now has a readonly property AreCommandsEnabled, allowing screens to disable their commands at certain times.
  • [WPF] DisplayScreens and ListScreens now disable their commands until their content is loaded.

v124.0.2

  • [ORM] DataContractEntityStore is now thread-safe thanks to a single big lock.

v124.0.1

  • [IMPORT] Better diagnostics for the case of accidentally using incorrect EntityMetadataDictionary.

v124.0.0

  • [IMPORT] The EditPipeline function operates on a slightly-better-abstracted 'Pipeline' object now instead of an import 'Source'. It has a utility function for setting custom converters.

  • [MODEL] New Optional<T> api: AsNullable(). Available only where T:struct.

  • [ORM] Improved the performance (roughly 2x) of Entity.Copy().

  • [ORM] AttributeBase now has a public property (T Value) which you can use instead (object DynamicValue) should you happen to know T.

  • [ORM] Bugfix-with-consequences: Relationships would allow their values to be read before they were fully initialised:

    • Attempting to do so now results in an exception.
    • This revealed that the previous method of calculating the original value of calculated attributes would calculate them before any relationships were initialised and before some attributes were initialised.
    • This resulted in many calculated attributes reporting that they had changes immediately after loading an entity, as they were calculated from uninitialised data.
    • The fix greatly improves the signal-to-noise ratio of the output of ChangeReporter when dealing with entities with lots of calculated attributes.
  • [ORM] Calculated attributes no longer require a DefaultSource. The source of the original value is now determined by whether or not the attribute it live-calculated. Live-calculated properties behave like DefaultSource.Calculated, and Persistent calculated properties behave like DefaultSource.Model. See calculated-attributes.txt for a breakdown of the precise behaviour of each type of calculated attribute.

  • [WPF] ListController now splits row model exceptions into message and stack trace when notifying of errors.

  • [WPF] The notification bar in the TDI shell now hides notification details within an expander. Usually this means that an exception message will be shown but the stack trace will be hidden.

  • [WPF] DigitCounter no longer has a fixed width, which used to effectively limit it to five digits. It can now be given a solid background to overlap things if it grows large.

  • [WPF] Section openness heuristics updated: CreateModal screens with only two sections now have them both open, regardless of whether either is a 'main' section.

  • [WPF] Breaking: ContentControllerBase's constructor parameters churn again for the last time - now it's all wrapped up in a The.WPF.Controllers.ContentOptions.

  • [WPF] Bugfix: ColumnPanel calculated its gutter-inclusive width incorrectly when several columns were present, meaning the trailing edge of content could be cut off.

  • [WPF] Bugfix: lists were generating columns for non-navigable properties.

  • [WPF] Bugfix: "Foo bar baz quux bim bam bom" would be displayed when an error was raised during RelationshipOptionsField summary generation.

v123.0.0

  • [IMPORT] The data-import stage is now robust and generalised, breaking down import-source structure as described by the event history into a more granular pipeline of composable operations. The pipeline edit API has been expanded accordingly; you can now describe arbitrary data moves, index lookups and the extraction of columns into relationships.

  • [IMPORT] 'Reimport', the creation of an updated schema root with any existing stem appended, now works with .theModels created by the original import prototype.

  • [IMPORT] The editable Structure object built by schema import now has some flags you can change for customisation and backwards compatibility:

    UsePluralisation             (default: true)
    UseLegacyColumnQualification (default: true)
    UseUnsanitisedEnumNames      (default: false)
    UseReferenceSections         (default: false)
    
  • [MODEL] SnapshotBuilder can now create empty models.

  • [MODEL] Bugfix: snapshot cloning had a subtle but pervasive bug, leading to clones which were .Equals() to the desired result but not correctly denormalised. This had implications.

  • [ORM] DataContractEntityStore has more builtin diagnostics and will be less permissive of cases that wouldn't work in SQL.

  • [ORM] DataContractPersistence.tt output was almost-harmlessly incorrect (it generated double-setters for each property of a contract during load).

  • [WPF] Calls to HandleErrors with an async function will now fail to compile and prompt the developer to use HandleErrorsAsync.

  • [WPF] TabbedShell now displays modal-screen errors 'attached' to the lightbox like the original shobiz implementation did.

  • [WPF] Bugfix: Lightbox resizing is now correctly bounded by the area it's contained within.

  • [WPF] Bugfix: Section context menu actions Expand All and Collapse All would sometimes fail to expand or collapse sections if they were wrapped.

v122.2.2

  • [ORM] Bugfix: Mutation would raise an InvalidOperationException if relationship changes were made while it was sending change notifications.
  • [WPF] Bugfix: FileControl would dereference nulls when clicking on Reset Column for a file field list column.

v122.2.0

  • [ORM] Major performance improvements to CalculateProperties. New The.Composition.Builder parameters can be used to tune it for an application.
  • [ORM] Import 'moves' are now 'extracts'.
  • [WPF] New control: VirtualizingWrapPanel.
  • [WPF] Performance and layout fixes to EnumSectionedCollectionField.
  • [WPF] Bugfix: EntityLink would sometimes fail to set its text.
  • [WPF] Bugfix: ListRowBase would sometimes crash in a Linq enumerator because of a race condition.

v122.1.0

  • [ORM] ImportManager.CalculateProperties now supports operating on subsets of the model - just give it an IEnumerable<IEntityInfo> (and feel free to use .Exclude()).
  • [ORM] Bugfix: CalculateProperties failed if you had any transient entities.
  • [WPF] ProgressModalController now has a clock!

v122.0.0

  • [ORM] New import features:

    • Not all data in a source table must be imported into that entity. You can omit some or (more desirably) import it into other entities.
    • Added generalised "Moves" - you can extract columns from a source table through any relationship, looking up and/or creating new rows in the target. Extracted columns can still be imported into the original entity, e.g. as a legacy attribute.
    • Multiple Moves from the same Table are independent; each move can unconditionally create a new row (value-like mode) or reference existing rows if they match the unique key formed by the move's columns (enum-like mode).
    • Importing into subclasses now supported, as is importing into or through inherited relationships.
  • [WPF] CreateController, DisplayController, CreateModalController, and DisplayModalController now have an overridable CreateContentSubcontroller method.

v121.0.0

  • [MODEL] Bugfix: The model editor would crash if any event property values contained commas.

  • [MODEL] The editor now has tooltips and rightclick-copy for the event list. This can be used to get the GUIDs of various model objects if you need them somewhere.

  • [ORM] Breaking: The.Composition.Builder's RegisterEntityStoreFactory method has been replaced with RegisterEntityStore to be easier to use and for consistency with other items like Authentication.

  • [ORM] The import 'hints' and system has been replaced with fully programmable imports. Both the 'Structure' AST built up by CopySchema and the 'Pipeline' AST built up by CopyData can be inspected and modified, allowing customised or fully synthesised imports. This allows importing DB structures which are not supported or not yet supported by modelling. To do a programmed import, call one of the new overloads of CopySchema or CopyData; you can supply either a prebuilt AST or a function to modify the discovered AST. This change also moves more functionality into the common import system, reducing the burden on individual IImportSource plugins - they are now pretty simple!

    New features supported by the pipeline mechanism: foreign keys which reference arbitrary columns (rather than just the PK) composite keys and composite key-targets automatic depluralisation all modelling events now supported rather than a subset custom conversions column-scoped instead of applying to all columns with the same name m:n relationships single-pass import - O(n) performance for n = rows in the database

  • [WPF] Breaking: ValueSectionedCollectionFieldBase has always given a subscreenFactory parameter, governing the creation of the contained list, to its base type. It and its subtypes now allow this to be overridden.

  • [WPF] SearchController now has overridable CreateCriteriaSubcontroller and CreateResultsSubcontroller methods.

  • [WPF] Bugfix: When there was one direct subtype of a generated controller that itself had multiple subtypes declared before it in source, ReflectionTypeFinder would incorrectly raise an exception complaining about multiple direct subtypes of a generated controller.

  • [WPF] The criteria panel of modal search screens now defaults to being open (previously closed) when there is no user preference.

v120.0.0

  • [IMPORT] Schema import now supports ambiguous columns - e.g. multiple columns with the same exact name.
  • [IMPORT] Data import is faster, with a foundation for further improved performance and more features in the future. This required breaking changes to IImportSource, though in practice there are no external implementations.
  • [IMPORT] Bugfix: ImportManager.CalculateProperties did not report anything when it finished, leading the UI to continue displaying "Recalculating properties".
  • [MODEL] The editor now has a contextual commands system - commands are accessible by icon buttons or right-clicking on appropriate areas. Editor commands are used to implement advanced features and to alllow extensibility by wrappers like The.Extension; they can come with bits of UI. For example, creating relationships now involves picking what to relate to, and deletion gives you a confirm dialog.
  • [MODEL] Relationship targets can't be changed directly anymore. This was not going to be useful in the long term, since you can't generate a migration for it - there's no SQL we can generate for "change E1<->E2 to E1<->E3", as there is not enough information to relate the IDs. New events and commands will be added to support 'moving' or 'extracting' properties to or through relationships.
  • [MODEL] Property viewing has been improved, particularly for relationships, which now show both sides at once.
  • [MODEL] Bugfix: tag display was showing the entity tags twice, instead of the property tags.
  • [ORM] Breaking: The.Composition.Builder's RegisterEntityStore method has been replaced with RegisterEntityStoreFactory, causing entity stores to be created with the entity metadata dictionary passed into RegisterMetadata.
  • [ORM] Bugfix (arguably): Entity metadata classes for supertypes and subtypes contained different copies of each of the EntityBase attributes.
  • [ORM] The.Composition.Builder.Configure no longer modifies the Builder instance.
  • [ORM] Significantly increased obfuscation quality by moving all top-level service managers between projects, from VB to C#. This allows other services to reference LicenseManager without being in an InternalsVisibleTo project, which cannot be fully obfuscated.
  • [ORM] Breaking: IEntityInfo.Attributes and .Relationships are now keyed by the property names of attributes and relationships rather than their modelled names.
  • [SQL] Breaking: The SQLPersistence template now produces a PersistenceDictionary data structure instead of ISQLPersistence implementations.
  • [SQL] Breaking: Persistence.Column is now immutable like its peers and has a new PropertyName property.
  • [SQL] The.SQL.Root.CreateEntityStore now creates a SQLEntityStore with persistence information filtered down to what will work with the provided entity metadata.
  • [SQL] The SQLPersistence template output now includes persistence information for legacy-only model elements.
  • [SQL] Column references in conditions and values are now reified by Emit, using persistence information, rather than when created.
  • [WPF] Bugfix: BLIRF and BLICF were incorrectly HasChanges=true when the property was IsPresent=false.
  • [WPF] Bugfix: Relationship field models were not consistently invalidating their model properties.

v119.0.4

  • [IMPORT] Bugfix: ImportManager.CopyData did not report anything when it finished, leading the UI to continue displaying "Waiting for writes to complete".
  • [MODEL] Editor bugfix: the properties list displayed everything in the wrong order, and if you reordered things it would just get worse.
  • [WPF] Checkbox collections are now sorted alphabetically.
  • [WPF] ProgressModalController's inaccuracy warning for current > max now includes more information about its current state.

v119.0.3

  • [ORM] Mutation.Dispose() was not exception-safe. This meant that failing user code during relationship change-notification could leak the mutation, preventing all future notifications.

v119.0.2

  • [WPF] InlineCollectionField now automatically updates on SetChanged even if you used a background thread.

v119.0.1

  • [WPF] InlineCollectionField now automatically updates on SetChanged.
  • [WPF] Fixed broken serialization of RecentItems.

v119.0.0

  • [WPF] MultilineTextBox and CollectionSelector now support font properties.
  • [WPF] LinkView/LinkModel have been removed - EntityLink is a standalone control once again. They were a poor abstraction for consistent styling; custom links can just style Hyperlink itself.
  • [WPF] EntityLink now supports alignment and font properties.
  • [WPF] The Inky theme is now more consistent about using bold for editable controls and normal-weight text for readonly.
  • [WPF] New 'Wireframe' theme for testing ui metrics with extremely high contrast. The idea is that we'll use this to work out good default templates and thicknesses, leaving colour and flourishes to real themes.
  • [WPF] Editable grids now have consistent field widths across rows.

v118.1.0

  • [IMPORT] Bugfix: ImportManager.CopyData would throw a NullReferenceException if passed a null 'progress' argument.
  • [WPF] SearchModal screens now hide their criteria by default - it tends to take up the entire lightbox. The criteria-openness state will be saved in user preferences.
  • [WPF] FieldControl now supports the Background property.

v118.0.2

  • [IMPORT] Even more accurate progress reporting.

v118.0.1

  • [IMPORT] More accurate progress reporting.

v118.0.0

  • [WPF] Breaking bugfix: IModel properties weren't propagating out of listrow fields to their outer screens. This is breaking because it changes the signature of ListRowBase.GetCustomFields().

v117.1.0

  • [WPF] ListRow model overrides can now reassign field properties, refreshing or replacing the data in a cell.
  • [WPF] Bugfix: LazyField's HasChanges and IsEditable properties were implemented incorrectly.

v117.0.0

  • [IMPORT] ImportManager.CopyData now throws an exception with a more helpful message when it fails to resolve a column conversion.
  • [IMPORT] ImportManager.CopyData will now automatically convert between Date and DateTime attribute types.
  • [MODEL] Deleting sections basically just didn't work at all. The editor now deletes sections when their last property is removed or moved out.
  • [MODEL] The optimizer had occasionally-unpredictable behaviour with large stems due to using an unstable sort.
  • [ORM] Bugfix: FooReport entity classes intended to allow access through null relationships would still throw NullReferenceExceptions when attributes were accessed.
  • [WPF] Removed SDIShell. Breaking, but nobody used it.
  • [WPF] Copying list rows was broken.
  • [WPF] IFieldModel has a new Unlabelled extension method that hides its label, and the Labelled extension method now reinstates label visibility if it was previously hidden.

v116.1.0

  • [IMPORT] The Status class used internally by ImportManager methods is now a common type in The.Utility. Other framework services or application code can use it to generically report stepped progress.
  • [WPF] New ProgressModal screen for running status-reporting operations with visual feedback.
  • [WPF] Bugfix: FreeLookupInlineReferenceField's constructor with an optional 'lens' parameter would throw a NullReferenceException if that parameter was not supplied.

v116.0.0

  • Unfortunately the two custom conversion features in this release are separate and do not interoperate. We'll look at changing that eventually.
  • [IMPORT] ImportManager now reports structured progress using a The.Import.Status instead of a string.
  • [IMPORT] Schema import does better name sanitisation.
  • [IMPORT] The data import pipeline is now considerably more robust and supports more model transformations inbetween schema-import and data-import.
  • [IMPORT] Added a folder-full-of-CSV import plugin.
  • [IMPORT] Type conversions are now supported (at least sufficiently for CSV). If schema import deduces AttributeType.String and you change it to AttributeType.Int before data import, IntegerProperty.Parse will run during the import.
  • [IMPORT] Custom type conversions are allowed with a new parameter to CopyData().
  • [WPF] Modal screens can now be used 'globally'; you can call IModalController.DisplayModal() without an IScreen.
  • [WPF] EntitySelector now handles null Choices and ItemsSources
  • [WPF] The Conversion module now supports custom conversions via its new RegisterConversion method.

v115.0.1

  • [WPF] Bugfix: autodiscovery of content controller overrides had broken.

v115.0.0

  • [ORM] Document properties now correctly implement ValueChanged.

  • [ORM] Added sort-by-collection support for in-memory EntitySets.

  • [SQL] Added sort-by-collection support for table-backed and query-backed EntitySets.

  • [WPF] No attribute fields are internal or abstract anymore - instantiate and inherit them all you like.

  • [WPF] Breaking: the parameters to ScreenManager.CreateContentController have changed.

    bool useSectionPreferences
    

    has been replaced by string preferenceNamespace = "Content", bool? forceSectionExpansion = null Preferences are now always used; the new parameters, if supplied, allow you to create separate preference sets and override the default heuristics to force sections to be open/closed by default. Create and CreateModal screens use this functionality to implement new default-openness heuristics.

  • [WPF] ExcelSpreadsheet has a new CopyRow method.

  • [WPF] File and Image fields now subscribe to ValueChanged events and update from model changes.

v114.1.8

  • [ORM] Bugfix: A bug where GraphChecker would sometimes produce WriteOps for entities that were already deleted has been fixed.

v114.1.7

  • [SQL] Bugfix: There was a bug in the VS2015 bug workaround.

v114.1.6

  • [ORM] The time complexity of HasChanges and NeedsSave has been greatly improved. (O(n!) to O(n))
  • [ORM] BLOBProperty.Compare and NullableBLOBProperty.Compare are much faster now.
  • [SQL] A bug in VS2015 led to SqlConnection objects being leaked and the connection pool filling up. A workaround has been added.

v114.1.0

  • [MODEL] The.Pluraliser now produces better results for certain words. In general, it should be closer to the old version; in particular, it has better support for spaces, underscores and camelCase.
  • [ORM] Legacy properties on legacy entities are now prefixed with "legacy".
  • [SQL] Fixed slightly broken output of CreateTriggers template.
  • [WPF] FreeLookupInlineReferenceField now has more convenient constructors. We need a more comprehensive treatment of relationship fieldmodels eventually but this was a particular pain point.

v114.0.0

  • This release requires an extension update.

  • [MODEL] CreateEntity and ChangeEntity events have a new optional property, DiagramNumbersV2 - this works the same as DiagramNumbers but receives an int[] instead of a preëncoded string.

  • [MODEL] Internally, we've got rid of the Model.xml used for test projects and are now dogfooding the new editor.

  • [OFFICE] Access import now supports the dbSingle field type.

  • [ORM] There's a new set of generated types, 'legacy' versions of entities. These can be found in the Your.Model.Legacy namespace and a framework handle which uses them can be built using Your.Model.Legacy.Entities.Metadata. Legacy entities ignore IsLegacy, both for properties and for entities themselves, and do not run calculated properties. They're essentially for migrations and datafixes, providing direct access to the true DB schema without respect to the 'current version' business logic. DataContractEntityStore now supports IsLegacy tables and columns (SQLEntityStore always did).

  • [ORM] EntityCollectionProperty<T> and EntityReferenceProperty<T> gained some high-level convenience APIs. They can now be cloned directly, and the nongeneric base versions support a visitor mechanism (similar to the one on IEntityInfo) which allows static recovery of the erased type T.

  • [ORM] Generic constraints in public API have been simplified. "T:IEntity,class" is no longer used and has been replaced with "T:IEntity". This is a breaking change for implementors of certain interfaces.

  • [ORM] Added SetOrderingType.Collection.

  • [ORM] Bugfix + performance improvement: cloning and also change-checking large graphs on multiple threads could deadlock, or (multiply) change-checking could deadlock with itself. Both operations have been rewritten to be trivially lock-free via purity, and can be safely multi-threaded.

  • [SQL] .Take() and .Single() now work together in queries.

  • [WPF] Relationship fields have been heavily refactored. All relationships now have 'inline' and 'sectioned' displays, the former for (editable) lists and the latter for the larger list/checkbox view. The content-form defaults are the same as before, but all relationship types can now be viewed and edited in lists. They obey the usual rules for IsInline and IsEditable, and can now also be used for sorting (collections are sorted by count). Inline list editing policy is now solely based on field count and custom overrides, as there are no more 'disqualifying' uneditable properties.

    Under the covers (potentially of interest to people creating custom UI), the inline fields use EntitySelector or CollectionSelector controls, and their readonly list counterparts render a simpler EntityLink (nee BoundLink, nee EntityLink), or CollectionLink. All of this control hierarchy has been refactored, along with combobox and multiline fields. Many small tweaks to editing widget UI have been carried out for consistency purposes.

  • [WPF] Added a new adapter, FieldModalScreen, which displays fields as (modal) screens. This replaces the specialised ContentSelectEntitiesModal screen.

  • [WPF] Range fields now support initialValue (which particularly improves search criteria).

  • [WPF] Lightboxes now support command groups.

  • [WPF] Bugfix: Now lightboxes are friendlier to keyboardists - IScreenCommand.IsDefault wasn't working in the default shell, and there were too many tabstops.

  • [WPF] Bugfix: ColumnPanel now is now more flexible, supporting use in size-unconstrained contexts and positioning with Vertical/HorizontalAlignment properties - previously it only really worked when you put it in an existing horizontal box, and would then always take up 100% of the allotted space. It could even crash with a Double.Infinity error if given too much freedom.

  • [WPF] Bugfix: lookup collections to reference data didn't display on Content screens if they were in the Main section.

  • [WPF] Bugfix: sorting lists by references was broken.

  • [WPF] Performance fix: hidden progress bars on Display and List screens were continuing to invisibly animate. When many sub-screens were displayed on a complex UI, this was causing pretty bad performance problems, like 10-20% of the CPU being used when totally idle.

v113.2.1

  • [ORM] Bugfix: The Entities template generated incorrect attribute indexes for EntityBase attributes in Props classes.

v113.2.0

  • [EXTENSION] Bugfix: the extension bugfix in v113.1.0 was incomplete and did not fix the bug.

  • [MODEL] New events: CreateAttributeV3, ChangeAttributeV3, CreateRelationshipV3, ChangeRelationshipSideV3. These events enforce a semantic change where the section id of an entity property must be explicitly specified at all times, rather than inferred to be a possibly-extant default, or "the one with the same name". These semantics are more robust and can be safely optimised in more situations than the V2 versions of the same events.

    This change is backwards-compatible with existing .theModel files.

  • [MODEL] In the editor, if the Main section had been removed from an entity, creating a relationship would crash or produce an invalid model.

  • [MODEL] Fixed a subtle optimizer bug in which the 'dirty-from' point of the added event sequence was off by 1, which could sometimes cause the version of the stem that was checked for redundant events (e.g. ones which make no change to the model) to differ slightly from reality. This, in turn, could lead to spurious event sequences being run through validation, and ultimately to a completely inexplicable crash. Alternately, it could lead to the inclusion of redundant events in the saved history which, again, could lead at a later date to an incomprehensible stack trace. Because of the unpredictable nature of this bug - it's akin to to a memory overwrite error in self-modifying code! - it could be behind every single error we've been experiencing in the model editor, or it might be that nobody's ever experienced the problem.

  • [MODEL] Implemented mediocre section-ordering support- "up" and "down" buttons.

  • [MODEL] Miscellaneous editor UI tweaks.

  • [ORM] ImportManager now has a test suite and will start stabilising over time.

  • [ORM] CopySchema now supports various permutations of preexisting and nonexisting model files.

  • [ORM] CopySchema now tries harder to sanitise column names and produce a model which can build out of the box. It should handle illegal characters as well as duplicate names.

  • [ORM] When used in serialise-to-XML mode, DataContractEntityStore did not fully deserialise its denormalisations. This led to LINQ queries against the de-serialised data failing.

  • [SQL] Query ToSet no longer claims to support OrderBy.

  • [SQL] Query ToSet, when Skip was not used or was used with an argument of 0, would return items with a different order to when Skip was used with a positive argument.

v113.1.0

  • [EXTENSION] Project templates were broken again :( I fixed them.
  • [EXTENSION] Bugfix: Visual Studio would crash if an InvalidEventException was raised directly out of SnapshotBuilder instead of as a wrapper for another exception.
  • [IMPORT] Table names are now de-pluralised when forming entity names.
  • [IMPORT] CopyData now provides a bit more diagnostic information - row counts, the sort of thing which will eventually be part of structured progress.
  • [IMPORT] ImportManager.CopyData now streams its writes in a way which should handle large data volumes. How large I don't know, but previously even 40k rows was failing. There's a customisable max batch size (use The.Composition.Builder to configure it).
  • [MODEL] Replaced The.Pluraliser with some MIT-licensed Microsoft code.
  • [MODEL] Bugfix: changing a currency attribute would crash the editor.
  • [ORM] Optimised bulk inserts - WriteOps no longer return back any data, meaning they are now many times (!) faster.
  • [ORM] IEntitySet<T> and EntityCollectionProperty<T> have a new AddRange method that should perform better than Add when adding multiple items at once.
  • [ORM] The relationship mutation mechanism, introduced to prevent deadlocks, now also detects and prevents three-way deadlocks - that is, contention between two separate locks and three threads waiting for them. Believe it or not, this bug occurred in practice.

v113.0.0

  • The.Framework and The.SQL no longer reference System.Configuration, which turns out to be incompatible with ASP.NET 5.
  • [IMPORT] Bugfix: When importing relationships defined by foreign keys in the source data, any nulls would throw the linking out of sync.
  • [IMPORT] Bugfix: ImportManager.ExecutePipeline was defaulting non-source attributes to null instead of their correct defaults.
  • [IMPORT] Breaking: Import pipeline execution is now common code, reducing the amount of work individual IImportPlugins have to do.
  • [IMPORT] Importing into entities with columns added post-schema-import now fills in those values using the modelled defaults.
  • [ORM] Relationship change-notification and concurrency have been reworked to fix bugs, notably including UI deadlock bugs. Any logical change to the current value(s) of a reference or collection should now result in a ValueChanged or SetChanged event (respectively), but not until after the 'batch of changes' is complete, free of locks, and it's safe to inspect or further modify the relationships involved.
  • [ORM] We're never ever going to use ++ as an expression again.
  • [SQL] Breaking: The.SQL.Composition.Builder was previously configured with a ConnectionString object - now it just takes a string. Instead of calling SetConnectionString(obj), you can call SetConnectionString(obj.ConnectionString).
  • [SQL] SQLWriter will now prevent nulls from incorrectly reaching SqlParameter values.
  • [WPF] Defining multiple criteria with the same name used to crash the application with an unhelpful error message. Now, it crashes with a helpful error message.
  • [WPF] Exceptions encountered when creating screens from top-level code (e.g. Application_Startup()) will no longer crash the application; instead, they'll display on the screen, creating a dummy tab if necessary.

v112.0.4

  • [MODEL] Adding a new section to an entity no longer results in a dialog box about "FORMATETC" when run under Visual Studio.
  • [MODEL] Creating relationships and then immediately changing their target was producing bizarre results - subsequent changes to the relationship properties would appear to take place on the opposite side, and sometimes created entirely invalid model files. This was a result of the editor UI incorrectly interpreting ChangeRelationshipSide events - because they were ordinarily combined into CreateRelationship events, the problem was hard to reproduce or pin down as the offending events did not appear in the .theModel.
  • [MODEL] The documentation for SortDirection has been corrected.
  • [MODEL] The documentation for DisplaySection has been corrected.
  • [OFFICE] ACEImportSource now supports dbDecimal.
  • [ORM] Running an import with a blank .theModel (one containing only a CreateModel event) used to fail or create an invalid file, but with the framework version of ImportManager it should be ok.
  • [ORM] Imported collections now go in pluralised sections, and lookup references go in Main.
  • [ORM] Imported entities are now TopLevel by default, so newly generated applications have a working menu.
  • [ORM] Imported relationships can no longer have a custom name equal to their entity name.
  • [ORM] Reference data now has an ascending default sort order.
  • [WPF] The subtitle for CollectionSections is now sorted.
  • [WPF] ListController no longer crashes to desktop in EntitySaved when an entity was deleted.
  • [WPF] Date and time pickers no longer start with the 'Enter a date' watermark.
  • [WPF] Range fields and filter textboxes are no longer sizing to an 'inherent' width, but to that provided by their container - they used to be too tiny to use in shobiz.

v112.0.3

  • [ORM] The interaction of relationship change events (EntityReference.ValueChanged, EntityCollection.SetChanged) with multithreading and data loading was difficult to predict and imposed unchecked requirements on higher-layer code. In particular, the events could sometimes be raised inside a monitor (synclock), potentially leading to deadlock if one application thread unwittingly held the lock while another thread raised the event and both threads were attempting to hold an application-level lock. This sounds esoteric, but occurred in practice with the WPF Dispatcher/main thread mechanism.

    Rather than continuing to create workarounds and adjust callsites, an internal mechanism is now used to guarantee that 'user' code (which could be app code or code from a higher layer such as the WPF module) is never synchronously executed inside a lock.

  • [ORM] Bugfix: PipelineBuilder would incorrectly throw a KeyNotFoundException if it observed a non-source column's name changing.

v112.0.2

  • [SQL] Boolean unary 'Not' is now supported in value-position in queries (translated into subtraction from 1). It was previously only supported in condition-position.

v112.0.1

  • [OFFICE] ACEImportSource will now give Access primary keys preference over fields when determining entity primary keys.
  • [WPF] Bugfix: A deadlock could be triggered by SetChanged being raised during a Display screen opening.

v112.0.0

  • The.Framework is now partly C#. This is mostly just an internal change, but it does have slightly ramifications: while we're in this process of transition, The.IServices is now a subinterface of The.Legacy.IServices, and the latter contains only a subset of services. If you somehow end up with a Legacy.IServices in application code and need the whole set you can just cast it.
  • [MODEL] Legacy model migration was putting some relationships in the Main section instead of their own section erroneously - it now follows the same semantics as did the legacy model.
  • [ORM] New service: ImportManager. This contains CopySchema and CopyData functions, which use an IImportPlugin to create a framework application from a legacy system. This whole API is very unstable and will be subject to rapid change.
  • [ORM] EntityBase has been simplified. EntityBase.Metadata and .GetText() no longer exist, and the design-time definition has been moved to a separate module. There are a few knock-on effects:
  • [ORM] IEntityInfo.Superclass is now optional, instead of having the special singleton empty-value "EntityBase.Metadata". I don't think any applications were using this property but it is a breaking change if so.
  • [ORM] The Text calculated property no longer has a special signature - like other calculated props, GetText is now protected internal rather than just protected.
  • [ORM] DynamicEntity has been removed (it probably didn't work).
  • [ORM] Bugfix: EntityCollectionProperty would not raise SetChanged when assigned an empty value.
  • [ORM] Bugfix: EntityCollectionProperty would not raise SetChanged when altered as a result of a change to the other side of a relationship.
  • [ORM] Bugfix: Once an entity had been deleted, saving it or its context again would raise an exception.
  • [ORM] Bugfix: Marking an entity for deletion twice (by calling .Delete() twice) would raise an exception.

v111.0.1

  • [MODEL] Legacy model migration was putting some relationships in the Main section instead of their own section erroneously - it now follows the same semantics as did the legacy model.
  • [SQL] SetFromQuery now supports the Skip LINQ operator.

v111.0.0

  • [EXTENSION] The event list in the model editor is now legible on a dark background.
  • [MODEL] SnapshotBuilder's default constructor is now public and it has a new CloneModel method. This makes it usable as a component within other folds over events.
  • [SQL] SQLWriter now throws a more descriptive exception when it receives an InsertEntity or UpdateEntity operation that does not contain a required column value.
  • [WPF] TimePicker now has a SelectedTimeChanged event.
  • [WPF] Breaking: DateTimePicker has been completely rewritten and now contains both a DatePicker and a TimePicker.

v110.0.0

  • [MODEL] New incompatible .theModel version to make history editing more robust. In particular, SectionV1 events are no longer supported; sections are now a first-class model element, referred to by a guid ID instead of a composite key and with support for tag events.
  • [MODEL] Many editor and optimizer fixes centred around the property list - adding/removing relationships and attributes, moving them, changing their names, updating sections, drag and drop.. the whole thing should be more reliable.
  • [ORM] Bugfix forward-ported from v86.10.5: Copying an unloaded relationship would result in the copy's DataState incorrectly being Loaded instead of Creating, meaning that it would not be saved.

v109.2.0

  • This release is about error-detection and recovery mechanisms for the model editor. Included changes:
  • HistoryEditor now has an event used to signal an error message to be displayed to the user. Different embeddings (the VS integration, hosting within framework WPF applications, etc) can handle this event to provide appropriate UI for errors. If no handler is specified, the error will be reported via an inadequate dialog box.
  • The editor (hopefully) now handles and reports errors at every point where model-specific processing is taking place - loading data from files or generating it from user input.
  • When optimizing the new-event stem, the result is now validated. If it doesn't check out, rather than appending it to the history, a rollback is performed and an error raised.
  • If an error occurs while the editor is hosted in VS, the extension disables further editing and displays the error as selectable text.

v109.1.0

  • [EXTENSION] Project templates now contain .theModel instead of Model.xml
  • [EXTENSION] Fixed the C# version of the CustomField item template
  • [EXTENSION] Added new item templates for commented criteriafactory and contentcontroller overrides - C#-only and a bit fragile, as the template parameter language is very limited. If you have trouble, try creating them at the project root and then moving the files to where you want them...

v109.0.0

  • [MODEL] New event: TagModelV1, which applies KVP tags to the model itself. The ModelSnapshot object has a corresponding API to look up tags.

  • [MODEL] Entity sections are now identified within the model by a unique identifier rather than their (changeable) name. Added new event versions CreateEntitySectionV2, ChangeEntitySectionV2, DeleteEntitySectionV2 which operate with the new semantics, as well as a 'bridging' event AssignLegacyEntitySectionID. These can be more easily generated by the editor and more safely optimized - in particular, it should fix a crash bug which was experienced when renaming sections.

  • [MODEL] Drag-drop ordering and sectioning of properties wasn't working when the editor was hosted inside Visual Studio. This is now fixed.

  • [ORM] Parsing data and retrieving default/modelled values of framework types used to require an instance of AttributeBase subclasses, which did not have public constructors. The ___Property classes are now accessible, and the functionality is also available statically:

    int IntegerProperty.Parse(string), int IntegerProperty.DefaultValue
    

    or dynamically: object AttributeInfo.DynamicParse(string), object AttributeInfo.DynamicDefaultValue

  • [ORM] DocumentPresenterBase (superclass of FileProperty.File, etc) no longer has or requires a Parent reference. This means you can use Files/Images without a FileProperty/ImageProperty.

  • [WPF] New WPFFrontend or WPFStandalone projects now contain an Excel output template by default.

  • [WPF] ModalResult.IsNotCancelled has been removed.

  • [WPF] ModalResult.IsCancelled has been added.

  • [WPF] Fixed a bug causing the first couple of columns in a list to be incorrectly ordered.

v108.2.6

  • [ORM] Support exporting rows containing nulls.
  • [SQL] The framework now escapes attribute names on select also.

v108.2.5

  • [MODEL] Numerous editor/builder bugfixes around the area of sections and relationships (creating, moving, renaming...).

v108.2.4

  • [SQL] The framework now escapes attribute names on update and insert, allowing column names like 'Key'.

v108.2.3

  • [SQL] Decimal columns were being created with precision specification (MAX,MAX) if no defaults were set, which is incorrect SQL.

v108.2.2

  • [MODEL] The .Display.Section property of EntityAttributeSnapshot and EntityRelationshipSnapshot was not being correctly updated if a number of section namechanges took places, leading to an inconsistent snapshot model.

v108.2.1

  • [WPF] TriggerScreenLink() moved to IServices, since you don't normally have an IShell.

v108.2.0

  • [MODEL] RelationshipSideSnapshot now has a property describing which side it is.
  • [WPF] IMenuBuilder.AddScreenLink() now returns an opaque token which can be used later to invoke the link with IShell.TriggerScreenLink().

v108.1.5

  • [MODEL] Editor: Relationship property names weren't correctly reflecting past ChangeEntity events.

v108.1.4

  • [MODEL] Optimizer: a sequence of events like

    CHANGE(id: 1, name: A), CHANGE(id: 1, name: B, data: X)
    

    was being mis-optimized to CHANGE(id: 1, name: A, data: X) instead of CHANGE(id: 1, name: B, data: X)

v108.1.3

  • [ORM] DataContractEntityStore now correctly reports the filename it's using (if any).
  • [WPF] Relationships weren't appearing correctly in lists.

v108.1.2

  • [MODEL] Optimizer: Create events in a stem are now 'hoisted' to the start of the recombined stem, preventing combined events from referencing a model element before its creation.
  • [MODEL] Optimizer: DeleteEntitySection events were insufficiently selective, and would cancel out Create events for other sections.
  • [MODEL] Snapshot: Processing a section name-change event didn't update all denormalisations, meaning that further namechanges would fail.
  • [MODEL] All these bugs lead to failures in the editor when handling sections roughly, or lightly, or looking at them funny.

v108.1.1

  • [MODEL] Editor: create attribute/create relationship buttons have been moved to the entity level instead of the section level. This lets you create properties in empty entities!
  • [MODEL] Editor: deletion of entities which contained relationships to themselves was crashing.
  • [MODEL] Optimizer: events which modified sections were being erroneously combined, leading to erratic behaviour when moving several attributes around.
  • [SQL] Bugfix forward-ported from 86.10.4: AsyncDatabase did not use ConfigureAwait(False), but is called synchronously from DocumentPresenter code, which could lead to deadlock.

v108.1.0

  • [MODEL] Editor feature: create new sections by drag+drop onto the "New section..." area.
  • [MODEL] Editor bugfix: add/remove attributes or relationships within a section didn't work properly.
  • [MODEL] Editor performance: the properties list is now virtualised even when grouped into sections, cutting down the load time and memory usage of shobiz-style Large Entities.

v108.0.5

  • Updated project templates to ward off bitrot (Controllers.tt has changed its empty-model output slightly).
  • [MODEL] Optimizer bugfix: tag events for the same object were being combined even if their keys differed.

v108.0.4

  • [MODEL] Editor bugfix: after multiple UI changes had been combined into a single event and then Undone, replicating one of the changes would result in the others being repeated also.

v108.0.3

  • [MODEL] Optimizer bugfix: creating two events which cancelled each other out by negation rather than combination would occasionally crash with a list-modifying race condition.
  • [MODEL] Snapshot bugfix: setting attribute Precision was not implemented.
  • [MODEL] Editor bugfix: the Precision data entry field was enabled even for types which do not have precision.

v108.0.2

  • [MODEL] Editor bugfix: CreateAttribute events which did not specify DisplaySection were incorrectly failing to process - they should default to section Main now.

v108.0.1

  • [MODEL] Removed the dependency on System.Collections.Immutable - it was requiring everyone to update to nuget 3.0.

v108.0.0

  • This release requires an extension update.

  • [MODEL] The new editor is ready. You can edit .theModel files using Visual Studio directly and create them with item templates; the file should be named after the namespace it contains. That is, Common.Generated.theModel will output classes in Common.Generated.

    This is a period of transition from old model to new, so Model.xml files will still work (and can still be edited using the old Class Explorer). If a .xml model is present, it will replace the .theModel file whenever generation runs. If the .xml is removed, the .theModel will be used directly. Once we're happy with the new editor, we'll remove support for .xml models entirely.

  • [MODEL] New namespace The.Model.Optimization contains an event stream compressor. Use it by creating a StemOptimizer with a 'root' list of unchangeable events (which can be empty), and then calling RebuildStem whenever new events are added; it will return an optimised stem to re-attach to the root.

  • [MODEL] Existing .theModel files must be regenerated, but this is the last time: from now on, model files are separately versioned, and we're at 1.0. Any future changes will be backwards-compatible, either by increasing the version number and importing old formats or by adding new event types and continuing to process the old ones. Despite the backwards compatibility, we should be able to evolve .theModel much easier than .xml - its deserialised form is a set of type-safe immutable classes generated, along with the serialisation code, from "The.Model/Events.t4".

v107.0.1

  • [MODEL] Bugfix: Model states with non-legacy relationships to legacy entities were not prevented.
  • [MODEL] Bugfix: Model migration did not make relationships to legacy entities legacy.

v107.0.0

  • [MODEL] Custom captions/DisplayLabels will no longer be uncamelled - their spacing and casing are up to the modeller.

  • [MODEL] DisplayOrder values set in the model editor are no longer directly connected to runtime display order. The snapshot model no longer has DisplayOrder at all, and the event model abstracts index changes over a dense sequence. In future we might move to an entirely different section/order representation in the event model

  • [WPF] Removed The.WPF.Shell.IndexController - its functionality has been folded into The.WPF.Controllers.SearchController. That is, Search screens now have a built-in create button and the ability to easily add more commands. The rationale here is that there's no actual use case for standalone 'search' screens which are not 'index' screens, and the informal subclassing was creating confusion.

    The only oddity about this change is that now Search controllers, and only Search controllers, have a GetCustomCommands() override. Perhaps this should be made a core feature of builtin controllers?

  • [WPF] Search screens now prevent their result lists from being in 'inline mode'.

  • [WPF] Content controllers no longer have separate GetGeneratedSections and GetCustomSections - they're combined into a single overridable function. This is a pretty breaking change, but it lets you specify a precise ordering of sections without needing to rely on DisplayOrder.

  • [WPF] Bugfix: BoundValueCollectionFields' Create button was sometimes incorrectly disabled.

  • [WPF] Bugfix: If a collection's caption and section were altered, they wouldn't be matched up by a template and the wrong kind of UI would be generated. This no longer occurs.

v106.0.0

  • [MODEL] BREAKING: Tags are no longer exposed from snapshots as a dictionary but instead through the new methods GetTag and GetAllTags.
  • [MODEL] Bugfix: Snapshot comparison relied on Dictionary<TKey, TValue>.GetEnumerator's ordering, which is not well-defined.
  • [WPF] Lists no longer control their own contexts. This might be inconvenient if you want to know what a list's context is - it doesn't know - but it allows modal edit screens to work within lists within fields within content screens within display screens.

v105.0.1

  • [ORM] Bugfix forward-ported from v86.10.3: When cloning an entity into a context that contained a copy of that entity with less loaded references, this could cause a loss of updates to those references.

v105.0.0

  • [EXTENSION] Model file location logic has changed.

    .theModel will now be used directly if no Model.xml is present
    otherwise, a .theModel will be [re]generated from the Model.xml
    otherwise, if neither is present, generation will fail
    

v104.0.0

  • [EXTENSION] The extension now stores user settings (template selections, editor UI state) in the suo file or registry rather than the model file. Template selections are still per-solution, but also per-user.
  • [EXTENSION] Added an item template for new .theModel files.
  • [EXTENSION] Bugfix: System.Windows.Interactivity, a nuget dependency of The.WPF, was being incorrectly detected by heuristics as a system DLL, causing templating to fail. Fixed with an exclusion for now, but we should come up with a more comprehensive solution.
  • [MODEL] BREAKING: Optional api improved.
  • [MODEL] Snapshot now exposes efficient indexed access to its top level attributes by ID.
  • [MODEL] Snapshots can now be compared and deep-cloned, for the purposes of programmatic editing/inspection.
  • [WPF] UNBREAKING: Double-clicking or pressing enter on rows of inline-editable lists no longer opens the entity in a lightbox.

v103.1.2

  • [WPF] Bugfix forward-ported from v86.10.2: There was a race condition in ImageControl that could lead to a NullReferenceException being thrown if the Image property was set to null while a thumbnail was being loaded.

v103.1.1

  • [WPF] Bugfix forward-ported from v86.10.1: There was a race condition in TabController.UpdateCounts that could lead to errors being thrown if advanced criteria were added or removed during its operation.

v103.1.0

  • [ORM] Forward-ported from v86.10.0: A new overload of ImageProperty.Image.GetThumbnailAsync that allows specifying a target MIME type different to the source image's MIME type has been added.

v103.0.0

  • [MODEL] Bugfix: Legacy migration was creating too many tags.
  • [MODEL] User settings are not saved in the new .theModel, just actual model data (see above).
  • [ORM] DataContractEntitySerialiser can now save/load its DB to/from disk. Its constructor takes an optional file path parameter; if omitted it will operate entirely in-memory, but if the parameter is supplied then the DB will be saved after writes and loaded before reads. This isn't as fast or robust as e.g. SQLite would be but it works well enough for testing and simple apps.
  • [ORM] When an existing entity is updated via a clone into its context, any attributes which change will now raise ValueChanged().
  • [WPF] Breaking: Paged lists have been replaced with infinite-scrolling lists which load data on demand. This is still paged internally and can be tuned with the PageSize WPF composition parameter. The Pager control has been removed, and ListRowModel.Entity is now an Optional<T> instead of a T, as it may be in an unloaded state. Otherwise, all screen layouts which worked with paging lists should work with scrolling lists. Overall UI performance is improved, but the main determinant of how fast a large list loads is now the number of columns visible. Adding too many columns which refer to expensive live calculated properties will cause rows to pop in more slowly.
  • [WPF] List screenmodels now expose the current EntityContext they're using (which may change on refresh).
  • [WPF] ReferenceDataController can now have its Open action overridden.
  • [WPF] BoundLink now has customisable fallback text for when an entity is not present/loaded.
  • [WPF] Bugfix: TabbedShell would NRE if closing a tab took long enough that a null SelectedTab was observed.
  • [WPF] Bugfix: Entering invalid data into a field of an inline-edited list would not invalidate the list itself, so you could still save the outer screen - alarmingly, this bug has been in there since October 2014 without anyone noticing.

v102.0.0

  • All templates are now based on SnapshotTemplate or HistoryTemplate; the legacy TemplateBase is gone. The legacy model itself still exists since we don't yet have a direct editor for .theModel files, but we can now develop one.

  • [SQL] Ported all remaining templates to the new model.

  • [SQL] Removed CreateTablesWithoutIdentityColumns template - the .sql file is still generated by CreateTables, similarly to how CreateTriggers generates both CreateTriggers.SQL and CreateTriggersWithoutAudit.SQL.

  • [WPF] Breaking: Criteria factories refactored. CriteriaController now takes one less generic parameter, and an ICriteriaFactory instance is specific to an IScreen. The generated criteria are now properties, rather than functions requring a screen - code which previously looked like this:

    GetCriteria(IScreen s)
    {
      yield return Foo(s);
      yield return Bar[s];
      yield return Bar.Baz(s);
    }
    

    will now look like this: GetCriteria() { yield return Foo; yield return Bar; yield return Bar.Baz; } Note the lack of indexed property - this was previously an issue in C#.

  • [WPF] Errors are now automatically handled in more cases: during user-written criteria code, and when a screencommand is invoked manually from code.

  • [WPF] Value reference fields and lookup collection fields now work better (the common thread here is BoundLink). Their entities open modally, allowing non-saved data, and the UI auto-updates.

  • [WPF] Lists used as the only section of a Content screen now have standard field chrome rather than appearing to be unlabelled.

  • [WPF] TabbedShell now supports infinite sidebars, sort of.

v101.0.0

  • This release is about shell convergence - bringing features from Shobiz into the built in TabbedShell, and reducing the amount of separate code to support. Shobiz now uses The.WPF versions of the following features:

    • Command buttons
    • Menus (IMenuBuilder)
    • Index screens
    • Lightboxes
    • Notification bars
    • ReferenceData and Browse screens
    • Sidebars (but the actual sidebars it uses are still custom) Remaining Shobiz-specific shell functionality includes:
    • Quick search
    • Pinned tabs
    • User switching
  • [ORM] Breaking: removed the 'IQueryHelpers' feature which was once used to produce custom SQL mid-query. It's no longer required and prevents further structure being added to SQL query translation (POCO query translation never supported it at all).

  • [WPF] Namespacing: a number of common/reusable features have moved from The.WPF.Shell.TDI to The.WPF.Shell.

  • [WPF] IScreenCommand.CommandRole has been removed. Screen VMs now instead have optionally-present properties for well known commands - e.g. IScreenModel.SaveCommand. The contract is that if the shell wants to perform a screen-level operation, it should use these commands if present, and if not, may implement the action itself (e.g. forcible closure of screens which don't have a CloseCommand). IScreenCommands are always for implementing response to user interface action, so there's no need to invoke them from programmatic UI-control code.

    Apart from being able to stick them in these well-known properties, no commands have special treatment anymore - there's none of the "must supply exactly 1 close command if you're a lightbox" stuff. All well-known commands are available on both modal and nonmodal screens, which means that you can use CloseCommand to prevent or constrain the closure of a normal screen now.

  • [WPF] Added a new experimental UI api: SidebarManager. "Sidebars" are instances of ISidebarController (which create an ISidebarModel); they're collapsible singleton screens with shell-specific display. Sidebars can be accessed by type and have access to the usual services/screen functionality. Sidebars can also be added or removed at runtime - for example, to display temporary information about an ongoing operation.

    The RecentItems view which was previously part of TabbedShell is now a standalone sidebar; this means that you can have projects which don't use it, or which use more relevant UI.

  • [WPF] Composition.Root.Instance is gone - all globals have been removed from the framework and from ShoBiz.Wpf, where Navigator is also gone. It is now possible to have multiple instances of The.WPF, as it already was for other framework modules.

  • [WPF] Display and Create screens now intercept refresh/close, list changes, and offer you the opportunity to save or cancel.

  • [WPF] The shell does the same thing at a global level if the window is closed with unsaved tabs, and adds notifications to the relevant tabs. If a notification is displayed in a non-focused tab, the header will now indicate it with the appropriate notification colour.

  • [WPF] ContentController.Get[Custom|Generated][Fields|Sections]() are now public.

  • [WPF] IMenuBuilder supports declarative access predicates - menu buttons are only available if these tests pass.

  • [WPF] IndexController and ReferenceDataController can be subclassed and customised.

  • [WPF] Lightbox notification heights are now correctly capped.

  • [WPF] The SelectEntities dialog, used for search and for LECFs, has been improved: it now has a "filter" field for cutting down the things to click on, and if you cancel it it doesn't do anything (previously this would be treated as re-applying the current selection!).

  • [WPF] Controller autodiscovery bugfix: if your project contains a class with the wrong constructor arguments, it will be skipped instead of attempting to instantiate it and producing an NRE.

  • [WPF] Hyperlink styling improvements:

    • Links in lists no longer override the default style.
  • [WPF] SectionControl styling improvements:

    • IsResizable can now be set without using an ISectionModel.
  • [WPF] EntitySelector styling improvements:

    • setting Background now correctly applies to the textbox and the dropdown, but not to the clickable button areas (these remain "button coloured")
    • now supports BorderThickness and BorderBrush, with the same defaults as TextBox and ComboBox

v100.0.3

  • [REPORTS] Bugfix: Nested loops in both C# and VB report templates were incorrectly parsed, leading to incorrect output.
  • [REPORTS] Bugfix: All '\par' substrings were removed from loop interiors, instead of only ones immediately leading or following a loop control statement.

v100.0.2

  • [ORM] Bugfix: Cloning an entity could throw a NullReferenceException if it had both: 1) a calculated attribute that referred to its 'props' or 'report' property and 2) a relationship to any other entity.

v100.0.1

  • [SQL] Bugfix: SQL persistence failed to account for parameters inherent to querying, occasionally causing queries with slightly more than 2100 parameters (the maximum) to be sent.
  • [SQL] SQL persistence will now also batch insert-relationship operations, of which there will generally be at least as many as of insert-entity operations. The same configuration item will affect the maximum number of inserts run at once.

v100.0.0

  • [ORM] All persistence ops are now serialisable as DataContracts, allowing the creation of proxy IEntityStore implementations. There's none actually shipped apart from the strawman RemoteEntityStore in The.Framework.Tests, but an application which needs proxying now has the rpc-mechanism-agnostic capability to implement it.
  • [ORM] Licence checks are no longer performed against code running in a process named vstest.console, and this and the other excepted process names are now case-insensitive.
  • [ORM] In-memory query translator now supports "is"/"TypeOf Is".
  • [ORM] Breaking: Lensed renamed to Box (just the concrete type - it still implements ILens). Box now supports datacontract serialisation.
  • [SQL] Query translator now supports "is"/"TypeOf Is".
  • [SQL] Query translator now supports .Distinct().
  • [SQL] The result of .Select().AsEnumerable().Count() queries is now more accurate using multiple joins - a more complete version of the fix in v99.3.
  • [SQL] Bugfix: the setting for SQL version conflict leeway was not being respected.
  • [SQL] Breaking: SQL persistence will now run multiple insert operations in a write operation batch as one call to SQL Server. The number of inserts run at once can be limited by calling WithMaximumBatchedInsertCount on The.SQL.Composition.Builder.

v99.3.0

  • Full support for C# in all project templates and code generation.
  • New single-project template "WPF Application (standalone)". This is a self-contained framework app with its model in a subdirectory, the easiest way to get up and running.
  • [SQL] Bugfix: .Select().Count() produced incorrect results - the Count at the end of a chain of selects and selectmanys got its source table confused.
  • [WPF] Some tweaks to the Inky theme - inner sections/grids take on a different colour, and the overlay now has a different inner de-bordering effect to create subtle deemphasis rather than an inward wash.

v99.2.1

  • [ORM] Bugfix: DataContractEntityStore would produce non-unique EntitySets if you used .ToSet() on a .Query() which called .SelectMany() over a many-to-many relationship and returned inDistinct results.

v99.2.0

  • [EXTENSION] Renamed "WPF Application" and "Console Application" templates to "WPF Frontend" and "Console Frontend".
  • [EXTENSION] New "Model+Persistence+Screens" template containing WPF GenOnly stuff; removed the GenOnly folder from "WPF Frontend". This better reflects how we're doing small apps, with a single generated-code project and a separate frontend.
  • [EXTENSION] "WPF Frontend" template now supports C#.

v99.1.1

  • [SQL] Bugfix: .Where(x => null check) was failing after select/selectmany in query translation

v99.1.0

  • [WPF] New theme: "Inky". This is the new default in templated projects.
  • [WPF] Both themes have been given core purpose and internal 'api' of colours which can be used to override them further. 'Inky' is a neutral/professional UI which you can customise by overriding SystemColors keys; 'Hercules' is a more shobiz-like UI with borders and lines in a bright primary colour - the HerculesLightBrush and HerculesDarkBrush keys can be used to customise its variants.
  • [WPF] Added a logo background to the shell sidebar.
  • [WPF] Bugfix: changes to ScreenTitle weren't getting picked up by TDIShell's tab headers. This was affecting Display screens particularly.
  • [WPF] Fixes for Conditional control bugs.

v99.0.0

  • [EXTENSION] Project templates had fallen out of sync with the framework. They now target .NET 4.5.2 and are designed to be used with nuget package restore in VS2015. For best results, follow the convention of naming the model project <appname>.Model

  • [EXTENSION] Added C# support for SQLModel and CLIFrontend project templates.

  • [EXTENSION] New item template: Custom Field, for use in The.WPF projects. It creates an IFieldModel and XAML view, data-bound together.

  • [EXTENSION] Bugfix: the Override Class item template seemed to think it should be generating T4.

  • [MODEL] The old relationship IsNavigable and IsLookup properties have been collapsed (in the new snapshotmodel) into a NavigationType. This has three values: Hidden, Lookup, Value.

  • [ORM] Implemented "environments" - a config- and run-time configurable string which indicates system modes like dev, prod, etc. The default environment is "Live", so that we're looking at a realistic UI; you can configure it as "Test" (which the builtin themes support) or some other string in order to make debug builds more obvious. It can be set up front by The.Composition.Builder.WithEnvironment(), or changed later via the EnvironmentManager service.

  • [ORM] New in-memory IDocumentStore implementation, The.Documents.TransientDocumentStore, for testing.

  • [SQL] The.SQL now supports C# output. This leaves The.WPF as the only module which still generates only VB code.

  • [WPF] The View side of The.WPF (the xaml, as opposed to the viewmodels) has been refactored and simplified. ThemeManager and the concept of 'themes' as a bunch of keyed resources which an application must apply are gone entirely. Theming is now optional, and done the WPF way: by applying default styles and templates. A number of new public controls have been added to The.WPF.Controls:

    CommandButton is used for all ICommand bindings to business logic actions (as opposed to pure UI actions). It can be arbitrarily styled or templated.
    ScreenHeader and FieldHeader support the application of text styles to blocks of label text.
    Overlay encapsulates the idea of a translucent "temporarily disabled" pane which we use for lightboxes, progress bars, etc.
    ErrorBorder is used as the default Validation.ErrorTemplate throughout an application (including in totally custom views), so error UI can be customised by styling it.
    Conditional is a higher-order control which presents its Then or Else property based on evaluating its If binding. This is useful in field views, when the visibility of some content potentially depends on an attached property. 
    

    Other controls have been made styleable and otherwise improved: Pager has been greatly simplified. ImageControl now has builtin tooltip functionality (which SHOBiz previously implemented). ColumnPanel now has sensible defaults. FastTabControl is now styleable. FieldControl has been massively simplified. The implicit contract for field views was that they should provide a label and various config bound to IFieldModel properties, as well as respecting attached properties. The first two parts of are now built in, and most fields will now care only about FieldControl.IsEditable (if anything). The SimpleField and UserField base classes have been removed. To write a field view now, just create a UserControl with databindings to whatever's on your model and use Conditional to track mutability if you need it. FieldControl and SectionControl can now also be used without an IXXXModel or datacontext at all - just give them direct content in XAML, or bind the Content property. In this case, you'll want to also set properties like Header which default to bindings. They're basically just HeaderedContentControl subclasses with custom templates which are defined, by default, by bindings to an expected viewmodel shape. Some controls have been made internal - ComboOrSearchBox, LinkOrTextBox, LockableButton, DigitCounter.. these are all really just primitives used in the implementation of public controls. You can still style these controls in a theme, you just can't use them yourself.

  • [WPF] The.WPF uses Environments to update application resources in a way which {DynamicResource} and ResourceReference will pick up. There are examples of this in Hercules.xaml - basically, if you define resource keys with an environment name appended, that version of the resource will be used when you're in the appropriate environment. So MyBrushLive replaces MyBrush when you're env "Live". There's no need for an actual MyBrush if you have specific versions for each environment.

  • [WPF] List screen refactored, adding some user-facing features: pressing enter on a list control will now open the selected row instead of moving down a row; users can now resize datagrid columns.

  • [WPF] Content screen models now support /dynamic binding/ to fields. They use the DLR (System.Dynamic) to allow binding to any field defined in a Content controller by name or caption. This supports writing custom Content views without requiring custom models. See The.Test.Screens for examples.

  • [WPF] Dispatcher.EnqueueInvoke now supports DispatcherPriority and has mandatory built-in error handling, via an IScreen or closure. "Just crash at a later date" should not be an option.

  • [WPF] NASA dates now support an optional unit specifier - day, month or year. T+1y will result in a date one year from now.

  • [WPF] Bugfix: relationship search criteria had an unclear UI if you put in impossible subcriteria.

  • [WPF] Bugfix: image controls' async loading was overwriting bits of the screen when rows were rebound rapidly (which happens in virtualised lists under load).

  • [WPF] Bugfix: image fields (not controls) had a deadlock issue if the document server was too quick to upload.

  • [WPF] Bugfix: decimal fields converted from decimal to string incorrectly, displaying rounded data like "1.3" for values like "1.29".

v98.1.1

  • [MODEL] Temporarily allow hidden lookups, since ShoBiz has a lot of them for some reason.

v98.1.0

  • [EXTENSION] Custom templates are now allowed in .exe projects, though it might be inconvenient in practice.

  • [EXTENSION] Bugfix: legacy model migration would fail if your model contained a default sort column from EntityBase.

  • [EXTENSION] Bugfix: legacy model migration failures were not handled by TemplateRunner.

  • [EXTENSION] Bugfix: legacy model migration failures handled by TemplateRunner were using System.Progress<T> as an IProgress, which failed to capture the synchronisation context due to the dispatcher thread having caused app domains, leading to unexpected concurrency and a crash in the proxy bus thread.

  • [EXTENSION] Bugfix: legacy model migration failures handled by TemplateRunner using the new synchronous BlockingProgress<T> were leaking a suspended thread.

  • [MODEL] The new model now supports 'tags' - application specific schema extensions. Entities, Relationships and Attributes can all have key-value pairs attached to them using the TagXXX events, which are exposed in the snapshot as a Tags property.

    This is particularly useful for attaching metadata to an imported model. For example, the legacy model migrator uses a tag to store refid->guid mappings, allowing stable re-migrations.

  • [MODEL] Added more flag cross-validity checks.

  • [WPF] The.WPF now performs a set of global overrides when an instance is first created, customising some undesirable WPF behaviour.

  • [WPF] Removed AutocompleteComboBox and AutocompleteTextBox, which were no longer used.

  • [WPF] Date pickers now support NASA dates - "T+4", etc.

  • [WPF] Subclasses of Models.ValueField (basically everything other than relationship fields) can now override .Value as well as .ModelValue

v98.0.1

  • [EXTENSION] Bugfix: Code generation would crash Visual Studio if run when any projects in the current solution had not been built.

v98.0.0

  • The framework now requires .NET 4.5.2 (previously 4.5.1) at runtime, and Visual Studio 2015 to build.

  • [EXTENSION] Supports two new template types, SnapshotTemplate and HistoryTemplate.

  • [EXTENSION] Full support for VS2015.

  • [EXTENSION] Improved error handling - more and clearer messages.

  • [EXTENSION] Bugfix: It's no longer an error to run a template when you don't have the relevant output file in your solution (it just won't do anything).

  • [EXTENSION] Bugfix: "overloaded semaphore" crashes shouldn't happen anymore, probably.

  • [MODEL] The.Model is now C#. The old project is temporarily named The.Model.Legacy; no new code is going here. The.Model.csproj references The.Model.Legacy.vbproj, which is part of the same nuget package; eventually The.Model.Legacy will be removed.

  • [MODEL] New model format: The.Model.ModelFile. This is an xml-serialisable type containing config and a list of historical events - CreateEntity, ChangeEntity, etc. The SnapshotBuilder type converts an event history to an externally-immutable denormalised graph. Hopefully this will provide a few different advantages:

    The new snasphot format is better for generating multi-language code. Core templates have been ported to support C#, and there's a new strawman test project The.Test.Model.Green.
    Historical events allow us to generate *migrations*, e.g. sql scripts which can transform the DB from one version to another and convert data.
    The new model is implemented as a library rather than an underspecified piece of XML; the template runner and gui editor are now part of the package, hostable in applications (e.g. codename jibnu).
    
  • [MODEL] XmlSerialiser(typeof(ModelFile)) produces custom but standard-compliant XML output for a minimal representation which is easy to diff/merge. It can still consume externally-authored or -modified XML.

  • [MODEL] There are two new template base classes: HistoryTemplateBase and SnapshotTemplateBase. These are for templates which run over the new model in either its canonical or denormalised form, respectively. The original TemplateBase will eventually be removed, but for now the IReadOnlyCollection<IEvent> and ModelSnapshot models are generated from the old ModelDefinition format.

  • [MODEL] New core type Optional<T> - it's a buzzword-compliant replacement for Nullable<T>. We've got by without this for as long as we could but it proved necessary in order to represent modelling concepts like 'this event optionally but not mandatorily lets you set or clear an optional value'. Features:

    works with value or reference types
    safe accessors GetValueOrDefault() and If(), instead of a throwing .Value
    supports LINQ and can be chained with T? in queries
    implicit construction when used as optional parameters (e.g. "new ChangeEvent(optParam: 5); new ChangeEvent(otherParam: 'c');")
    implements standard comparisons without crazy Nullable.Equals requirement
    XML-serialisable 
    

    The rest of the framework might not use Optional any time soon, but it's available to application code if desired.

  • [MODEL] The new model has heavy unit test coverage instead of none.

  • [MODEL] The 'AdminOnly' flag has been replaced with a new take on god mode: if you're admin, the DisplayForm/DisplayList/DisplaySearch flags don't apply and you just see everything. Note that this is not actually implemented yet (and AdminOnly was also not implemented, except for search criteria).

  • [ORM] The entity metadata dictionary is now a special subclass with a method that returns all subtypes of an entity.

  • [ORM] Optimised The.Security.PresetAuthentication.

  • [ORM] Bugfix: Cloning entities recalculates the calculated properties of those entities in the target context, but it was doing so in a flat loop without any dependency information, and so it could result in incorrect values if a persistent property - e.g. Text - depended on another persistent property. This was the cause of SB-2873.

  • [REPORTS] The.Reports is now C#.

  • [REPORTS] The RTF/Razor parser now produces error messages indicating expected vs received input, rather than just failing mysteriously.

  • [WPF] Breaking: All ways of creating Create and CreateModal screens have a new 'bypassTypeSelection' flag - this causes the entity selection drop-down to be hidden and locked to the given entity type.

  • [WPF] Breaking: DataGridLinkColumn has been removed. A DataGridImmutableLinkColumn with .IsMultipleElements = False should be used instead.

  • [WPF] New VM: EmptyModel, which can be used when there is nothing to display; it is templated with an empty Control.

  • [WPF] New VM: EntitySubtypeEnumField, which allows selecting one of the concrete subtypes of an entity type from a drop-down list.

  • [WPF] New control: FileSelector. This provides a drag-drop textbox and a Browse button for picking a single file or folder. if SelectFolder or Extension are set it will also validate dragged paths.

  • [WPF] Create and CreateModal screens now work for entity types that are abstract or have proper subtypes - unless there is only one concrete subtype or the new 'bypassTypeSelection' option (below) is used, these screens now have an EntitySubtypeEnumField at the top to allow selection of the entity type to create. The Content screen underneath will be synchronised with the entity type currently selected. This means the viewmodel no longer contains a typed entity reference, but controller subclasses can now use base.Entity for that.

  • [WPF] ControllerBase and ModalControllerBase have a new overridable Sub OnModelCreated(); this is called after the model is created and initialised and the Model property is set.

  • [WPF] List column layout has been improved by removing the 'special' terminal column. This improves appearance and performance, removes scrollbar flickering, and fixes the crash bug SB-2869.

  • [WPF] Bugfix: EntitySets backing ListControllers can now safely be updated from non-Dispatcher threads.

  • [WPF] Bugfix: hyperlinks in the first column of a list were not respecting its overridden DoOpen command.

v97.0.0

  • [DOCUMENTS] The.Mongo has been removed. We have no plans to ever actually use MongoDB, and the whole IDocumentStore abstraction could use rethinking. It can be resurrected from source history easily enough if needed.
  • [EXTENSION] Bugfix: When used in VS2015, template running would experience intermittent file locking issues. This was due to VSSDK Solution/Project data structures being 'active' at the same time as filesystem calls were made. That code has been separated and the issue should be fixed.
  • [WPF] Lots of fallout from the MVC refactor-
  • [WPF] Breaking: IControllerFactory's modal-controller-returning methods now have concrete return types. This fixes a bug where AutodiscoveryControllerFactory would return the same modal controller from all such methods.
  • [WPF] Breaking: The 'init' parameter for IControllerFactory.CreateCreateController and .CreateCreateModalController is no longer optional.
  • [WPF] Breaking: EnumFieldBase's Choices and Selection properties are now abstract rather than virtual-but-not-implemented.
  • [WPF] Bugfix: There was incorrectly a singleton search screen.
  • [WPF] Bugfix: EntitySelector.SearchButton_Click did not handle exceptions.
  • [WPF] Bugfix: ModalControllerBase was incorrectly double-initialising.

v96.0.0

  • All use of Managed Extensibility Framework has been removed. Presumably we are no longer manageable, extensible or a framework.

    Note on terms in the following changelog: like every MVC framework, The.WPF has arbitrary idiosyncratic definitions. MODEL: Implements IModel. Aggregates data in a form suitable for binding. VIEW: Inherits FrameworkElement. Presents bound data using WPF controls, manages user input. CONTROLLER: Implements IController. A use case sequencer; contains business logic and communicates with the lower application tiers. Screens have one each of these; fields have only a model and a view. The equivalent of the 'M' layer from other frameworks is the entity object system from The.Framework, but this is not exact: ORM objects are used by our Models to store data and provide change tracking, as well as by Controllers in business logic workflows. In general, we have an n-tier architecture, using MVC only for the UI layer. Here's a needless comparison to other major confusions: +------------------+---+------+-------+ | Prism (MS) | M | V | VM | +------------------+---+------+-------+ | corresponds to | - | View | Model | +------------------+---+------+-------+ +------------------+---+-------------+------------+ | Cocoa (iOS) | M | V | C | +------------------+---+-------------+------------+ | corresponds to | - | View, Model | Controller | +------------------+---+-------------+------------+ +------------------+---+------+-------------------+ | ASP.NET | M | V | C | +------------------+---+------+-------------------+ | corresponds to | - | View | Model, Controller | +------------------+---+------+-------------------+ +------------------+------------+-------------+---+ | Smalltalk | M | V | C | +------------------+------------+-------------+---+ | corresponds to | Controller | View, Model | - | +------------------+------------+-------------+---|

  • [EXTENSION] The WPF frontend project template now includes an easy place to customise the theme, with commented samples.

  • [EXTENSION] Class name changes are now detected on model-load so that templates continue to work.

  • [EXTENSION] The code generator will now display "Generation succeeded" or "Generation failed" in the VS status bar depending on whether any errors occurred. In the event of failure, check the Output pane for messages.

  • [WPF] Rather than MEF, controllers are now created by an injected IControllerFactory. There's a generated implementation <model>.Screens.GeneratedControllerFactory. You can subclass this for full customisation - using a DI container, for example - or wrap it in the built-in AutodiscoveryControllerFactory. The autodiscovery mechanism finds controller subclasses by inspecting DLLs, similar to how MEF overrides worked but without requiring attributes to explicitly export them. Applications usually do not need to access autodiscovery explicitly- WithOverrideSources() on the builder will take care of it.

  • [WPF] Built-in controllers can now be subclassed to customise their functionality. They inherit from ControllerBase<TModel,TView>, which adds overridable CreateUninitialisedModel() and InitialiseModel() methods. For custom controllers, you can use this same base class, or from CustomControllerBase<TModel,TView> for a simpler implementation which is not intended to be further overridable. Finally, there's also ControllerBase<TModel>, which does not do data templating. Modal controllers have three equivalent base classes also.

  • [WPF] Overriding models no longer uses the Export attribute, and IModelFactory no longer exists. You can override CreateModel() or CreateUninitialisedModel() on controllers to produce a custom model subtype.

  • [WPF] Overriding views no longer uses the Export attribute, and the IXXXView<T> interfaces no longer exist. You can override SelectView() on controllers or inherit from ControllerBase with an appropriate TView.

  • [WPF] Overriding controllers is now also how you hook lifecycle events - OnSaving, OnCreated, etc. This includes the new OnClosed, which replaces the IDisposable implementation on the previous ControllerBase.

  • [WPF] The static controller-creation API has been replaced with a new ScreenManager service. Controllers can be created either by constructors or using WPF.IServices.ScreenManager e.g. either this form to create a specific type:

    new `The.WPF.Controllers.SearchController<MyEntity>(wpfServices)`
    

    or this new method, preferred as it looks up overrides:

      wpfServices.ScreenManager.CreateSearchController<MyEntity>()
    

    but no longer this: Generated.Controllers.MyEntityCreate.Create(e) Note that the type of the controller there is now T.W.C.SearchController rather than just T.W.C.Search. This excessive brevity was causing ambiguity issues with, for example, List<T>. Typed nonmodal controller classes are exposed by the construction service - you get a Controllers.Display<T> rather than just an IController<Models.Display<T>>. This means that controllers can have a public API, and some now do - in particular 'lifecycle' events have moved from viewmodels to controllers. Modal controllers are still exposed as IModalController<TResult> for now.. since they control their entire presentation experience, it seems like there's less reason to automate them externally. If we come up with a use case, this could be changed. ScreenManager also enforces security and caching within the framework. Previously these could be circumvented, even accidentally, by application code.

  • [WPF] Screen models no longer require two-phase init. In particular, ScreenModelBase no longer has a mutable-once .Screen property. Now, the IScreen is just a constructor parameter. Screen commands can also be created with an indirection - Func<IScreen> instead of IScreen - allowing pre-creation of commands without having to use Lazy<T>.

  • [WPF] Content screens have changed the most, as the generated FooContent model is now a generated controller. However, the field/section override remains nearly the same. Differences include:

    Lookup Factories no longer exist. When overriding a generated Content, you can now optionally supply a choice set to lookup fields.
    There is no longer a GetSectionDefinitions() function - this didn't really interact well with DisplayOrder. Use the .Sections property instead.
    The .Entity property is now readonly - the entity of a content screen is set in its constructor and cannot be later modified. This is a significant reduction in complexity, with performance benefits - in practice, this functionality was being used by only one case in ShoBiz, which got it wrong anyway.
    Consequently, the EntityChanged event has been removed - embedders of Content can assume that it is fully initialised all the time. 
    ShowOnForm now works better - it will not generate seemingly-functional overridable factories for fields that never actually exist.
    
  • [WPF] Display overrides are much simpler now. They do not have to watch for Content.EntityChanged, and a new OnLoaded event (the twin of OnSaved) means they don't have to watch Content itself either.

  • [WPF] List now has a CreateRowModel() - Models.ListRow was previously an IScreenModel overridden by MEF. Now it's just an IModel.

  • [WPF] Criteria now has quite a large public API. Criteria factories are still a separate type, and use the same autodiscovery mechanism as controllers themselves. This is kind of a hack, but rewriting criteriafactories to fit them into criteria controllers is a big chunk of extra work and wouldn't gain us much.

  • [WPF] JIT templating: when inheriting from ControllerBase or FieldModelBase, you can supply an optional TView type parameter to get automatic just-in-time data templating - the first time the model is to be displayed, its view will be added to the application resource dictionary. This works with generics and avoids the need for up-front templating when a user might only use a small portion of an application. 'Nominal' templating, the "ViewModel"-"Model" string matching thing we inherited from shobiz, has been deprecated (but not yet removed).

  • [WPF] Bugfix: TDIShell was opening ScreenLinked index screens twice the first time.

v95.1.2

  • [MODEL] Anchor the property list for class editing a bit higher up so that it doesn't get overlapped by the default text/default order fields.

v95.1.1

  • [WPF] Disable obfuscation of The.WPF.Views types - the new ExtractPropertyPath system is broken by this, because the reflection that it does cannot find the same paths at runtime that were visible at compile time.

v95.1.0

  • This release requires an extension update for updated project templates and to handle the new model properties.
  • [ORM] Forward-ported many bugfixes from the v86 branch.
  • [ORM] Added two new model properties on EntityDefinition/ucClass, FormatString and FormatStringArguments. These are now used to provide the default GetText() implementation for an entity that has no override.
  • [WPF] Added a new Menus template which generates a set of top level menu buttons for the TDI shell. This is used in the WPF project template.
  • [WPF] Added a new model property on EntityDefinition/ucClass, HasIndex. Classes with HasIndex will get a top-level menu button which opens a special 'index' screen - it's a search screen, but with a Create button.
  • [WPF] Previously, screen controllers and models were using global variables and property injection to access framework handles. All their dependencies are now provided by constructor injection - ControllerBase takes an IServices, ScreenModelBase takes an IScreen.
  • [WPF] The remaining templates all now live in <Model.Namespace>.Screens - previously they were scattered over <Model.Namespace>.Models, <Model.Namespace>.Controllers, <Model.Namespace>.Views and <Model.Namespace>.Search.

v95.0.0

  • [ORM] Entity types are now created using constructors, bringing them one step closer to standard objects. Conceptually, SomeEntity and EntityKernel are now a fixed pair, with the kernel created by the construction of the typed entity and assigned readonly. Gory details:

    • Entity.Create(ctx) has been removed
    • There's a new public constructor Entity(ctx)
    • IEntityInfo.WrapEntity has been removed - kernels are always created pre-wrapped
    • IEntityInfo.CreateEntity still exists but now calls the entity constructor rather than the other way around, e.g. it's for the use of dynamic code to create arbitrary entities
    • IEntityInfo.LoadEntity now takes an initial DataState to load - it covers cloning as well as populating from the datastore, or whatever other way we might have to load one
  • [ORM] Collection properties are no longer readonly. You can now assign to an entity collection, passing in an entityset, which will replace the contents of the collection, taking care of removing or re-adding existing items, etc. This is backed by a new method EntityCollectionProperty<T>.ReplaceAll(IEnumerable<T>), or in the dynamic case, EntityCollectionProperty.ReplaceAll(IEnumerable<IEntity>).

  • [ORM] Removed the IEntitySet.Context property, which never really did what it said on the tin, making initialisation of in memory sets more convenient.

  • [ORM] The combined result of the above changes is that you can now write initialisers like

      new Human(ctx) {Name = "Child", Age = 10}
    The way this works is that by the time the constructor call finishes, the ORM is initialised and it's ready to have properties updated. Attributes "Name" and "Age" would immediately be HasChanges=true. This also works for relationships, so you can write single-statement initialisations like
      new Human(ctx) {Wears = new Hat(ctx)}
    or even
      new Farm(ctx) {Animals = new `EntitySet<Animal>` {new Dog(ctx), new Sheep(ctx)}}
    

v94.0.1

  • All runtime libraries (the nuget packages The.Model, The.Framework, The.WPF, The.SQL, The.Mongo, The.Reports) and The.Extension are now obfuscated. Obfuscation applies to release builds only - those builds are slower as a consequence. Building the framework now requires Eazfuscator.NET to be installed; there should (in the moral sense) be a copy on ACDC. Special PDB files are also built which can be used to debug the obfuscated libraries. They should not be distributed to clients.

    There are no functional changes in this release of the framework.

v94.0.0

  • [ORM] Autonums have been reimplemented. Rather than a client-side prediction mechanism, autonums are now fully implemented by the IEntityStore, and the value of an inserted autonum is passed back to the client using the same channel as row-version attributes. This has a number of useful implications:

    * How exactly an autonum is generated can be fully specified by a datastore in store-specific terms, allowing us to guarantee sequentiality (and there are now unit tests for it).
    * All persistence is now fully serialisable; the only operations left on IEntityStore are ExecuteReads() and ExecuteWrites(). This makes it trivial to implement a proxy/'remoting' entitystore when we want one (which was once considered high-priority; I'm not sure about the current status).
    * Any arbitrary combination of autonums and calculated properties will work correctly.
    

    The major remaining limitation is that we still have at most one autonum per entity. This is not strictly necessary, but it simplifies the implementation and allows us to continue using native SQL identity values - which have good performance and distributed-system characteristics.

  • [ORM] The .θL license file format is now documented and versioned. The.Utility.Pickle enforces this versioning - we don't want to accidentally create some unversioned format in future.

  • [ORM] Rather than waiting for .NET 4.6 where RSA is properly supported, the signature in .θL files is now done with ECDSA using the P-256 elliptic curve. If we want to upgrade to RSA in future (this would mean faster verification, and the ability to use longer keysizes) then we can add a new version of the format.

  • [ORM] Bugfix: app-hash license check now works when the entrypoint is unmanaged.

  • [ORM] Bugfix: FirstOrDefault() queries were not returning null, but instead throwing exceptions (introduced in 93.0)

v93.0.0

  • The major new feature in this release is a licensing subsystem. Persistence ops (reading/writing the entity datastore) will fail except when accompanied with a valid license token. Tokens are created within a temporary scope for 'privileged' operations (prefs, auth, etc) or supplied permanently by a grant check operation in the new LicenseManager. Application code does not need to take any account of licensing unless the application implements a custom The.ISomething plugin, in which case its implementation will be passed opaque tokens and must pass them on to the PersistenceManager.

    Signed grants are loaded from license files - the location is configurable, but by default a license will be named after the main/entry-point assembly, such that for "ShoBiz.exe" there is a "ShoBiz.θL". θL files are created by the new "license" option to The.Utility. License file validity can be restricted to a specific binary file and/or within a date range. Example: utility.exe license --hash --to "dec 2015" Some.Program.exe will generate Some.Program.θL. There are two new item templates available in The.Extension - a through-2015 license and a through-2016 license. These pre-signed files can be distributed alongside any framework application for now. A number of future improvements are planned:

    • obfuscation of the framework dlls to discourage reverse-engineering of the license check
    • real cryptographic signature in the license files - the .NET RSA api is improving immensely in 4.6, so it'd be nice to wait for this if we can.
    • refactoring of the licensing composition structure - it's a bit awkward to set up right now, though I've already done the setup for the project templates.
    • more licensing restriction options such as a 'model hash'
    • retrieving the license from a server rather than a distributed file
  • [ORM] Partial VS2015 support - only The.Extension still requires 2013.

  • [ORM] For technical reasons, all IEntity implementations must now be of reference rather than value type (no structs). They always have been up to now but it wasn't actually required. We may be able to relax this restriction again in future but it doesn't seem to be hurting anyone.

  • [ORM] New module The.Utility.Pickle which can be used for simple no-config serialisation of objects.

  • [WPF] The singleton-using EntityLink control has been removed, replaced with LinkView and LinkModel; there's also a BoundLink control which wraps them, functionally similar to the old control except that it requires a Screen binding as well as an Entity.

  • [WPF] The IScreenFactory type cluster has been removed, replcaed with a single IControllerFactory which is implemented by generated code and can be extended to provide custom controllers. The new screen creation API is along the lines of:

      wpfServices.ControllerFactory.CreateDisplayController<Place>(somePlaceID)
    

    This is a significant step toward removing MEF entirely, but we're not done yet.

  • [WPF] TDI shell: performance improvements and bugfixes.

  • [WPF] Errors in the creation of screens will now generally be propagated to the outermost controller and then displayed as a notification, rather than resulting in silent failure.

v92.1.1

  • [SQL] Bugfix: CreateTables.sql was trying to change ntext columns for non-nullable attributes to non-nullable nvarchar(max) columns instead of nullable nvarchar(max) columns, regardless of the value of EnforceNullability.

v92.1.0

  • [WPF] TDI shell: Removed hyperlinks
  • [WPF] TDI shell: Added a reference data editor screen
  • [WPF] WPF application/window name is now customisable in the app.config

v92.0.0

  • [ORM] Removed the EntityOverrides template. Overrides/partials are optional now, only necessary for types where you want to implement a calculated property - for those ones, there's an new item template available. Right-click the Overrides folder (or whever you want to put them) -> Add -> New Item -> Template "Override Class" in category "The.Entities"."

  • [WPF] EntityLink can now be used without breaking the designer, but for real this time.

  • [WPF] Renamed IModelessController to IController.

  • [WPF] The.WPF.Controllers.ModelessControllerBase<TModel> was an alias for ModelessControllerBase<TModel,TDefaultModel>. This circumvented the viewmodel-overriding machinery to make it slightly more convenient to create fully custom screens. It's been replaced with a new ControllerBase<TModel> which doesn't do vm-overriding at all, but does have a convenient interface for controller-overriding, which will be the future direction for screens generally.

    There's another subclass ControllerBase<TModel,TView>, which will create datatemplates on demand - no more long startup time or handwritten ResourceDictionaries. You can still override the either the model or the view, simply by subclassing appropriately, with no more two-phase initialisation. There's an example in the WPF project template. tl;dr: create custom screens by implementing MyCustomController : ControllerBase<MyModel,MyView> and overriding CreateModel(IScreen).

  • [WPF] TDI shell: IMenuBuilder.AddScreenLink() now correctly(?) recreates tabs that were closed, rather than opening the old ones.

  • [WPF] TDI shell: cleaned up all the shobiz-import stuff, getting rid of binding errors and minor layout bugs.

  • [WPF] TDI shell: added recent/pinned items sidebar.

v91.0.0

  • [EXTENSION] Two new project templates - Console Application and WPF Application. These scaffolds produce frontend projects intended to be paired with a model project.
  • [EXTENSION] Template loading improvements - there's no longer a dependency on the order of dll loads.
  • [ORM] New IEntityStore implementation: The.Persistence.POCO.DataContractEntityStore. This schemaless backend stores entity/relationship data in serialisable objects which can be saved to a file - although this functionality isn't actually exposed, so right now it works as an in-memory store. It supports the full range of queries and so on, but is not thread-safe. There's a new DataContractPersistence template which goes along with it; add this to your model project if using the in-memory backend.
  • [SQL] QueryTranslator now supports .OfType<T>() for queries, and .Cast<T>() and .OfType<T>() for enumerables.
  • [SQL] The templates 'CreateTables', 'CreateTablesWithoutIdentityColumns', and 'EnableIdentityColumns' now support both: increasing the length of existing nvarchar columns when the model attribute's length has increased, and converting existing ntext columns to nvarchar(max). These conversions are metadata updates and do not require significant processing to perform.
  • [WPF] New shell The.WPF.Shells.TDI.TabbedShell. Unlike the existing SDIShell, this one is for production rather than testing, and supports customisation hooks. It's a SHOBiz-like environment, with menu buttons, notification bars and keyboard shortcuts. Modal screens are displayed in a lightbox within their tab.
  • [WPF] New converters in The.WPF.Utility: CompositeConverter, GreaterThanConverter, BooleanAndConverter. Some of these may go away in future; we have way too much conversion going on right now, which should be moved to VMs.
  • [WPF] Added VisualTreeExtensions in The.WPF.Utility for searching and enumerating visual children.
  • [WPF] List creation has been simplified - like other controllers, there's just one factory method now. Eventually all controllers may be created by something similar to IControllerFactory.Create<T,TArgs>()
  • [WPF] WPF templates now put themselves in the model's namespace regardless of your project settings.

v90.1.0

  • Merge the following changes from v86.4.2~v86.7.0:

  • [ORM] Bugfix: WriteOneReadManyDocumentStore.GetImageMetadata threw an InvalidOperationException when the requested document was found in multiple stores.

  • [ORM] WriteOneReadManyDocumentStore better follows the emerging contract for IDocumentStore.GetImageMetadata:

    If you have the image, return its metadata and all of its thumbnails that you have (if any)
    If you don't have the image but have some of its thumbnails, return an ImageDocument containing only the thumbnails and ID = Guid.Empty
    If you have neither the image nor any of its thumbnails, return null
    
  • [ORM] AppDataPreferenceStore has a new Create factory method that handles and logs XML parsing errors. The existing constructor has been marked as obsolete.

  • [WPF] ValueField(Of TModel, TView, TTraits)'s and ValueField(Of TModel, TView)'s constructors are now public.

  • [WPF] Criterion(Of T) now has a WithDefaultSubcriterion method that can be used to override the subcriterion that is used when the criterion is default and begins selected when the criterion is advanced.

  • [WPF] All nullable value-type attributes will now have a 'Has value' subcriterion generated.

v90.0.3

  • [WPF] Fix race condition when loading a Content screen on a background thread (though we shouldn't be doing this).

v90.0.2

  • [ORM] Fix race conditions in EntityCollection, making it threader safer.

v90.0.1

  • Fix dependency on prerelease nuget package.

v90.0.0

  • Reorganised some stuff according to recommended project structure; in particular, staging/ is now artifacts/
  • [DOCUMENTS] Shared source files let us now have more comprehensive tests for each IDocumentStore implementation.
  • [REPORTS] New package The.Reports so that if you're just using precompilation you don't have to take a Roslyn dependency in all your projects.
  • [REPORTS] ReportManager now supports parsing/generating VB as well as C# reports. The C# support is slightly more comprehensive but VB-quasirazor mode should be good enough for shobiz stuff.
  • [SEARCH] Specs are no longer generated for transient entities.
  • [SEARCH] Search and Criteria screens are no longer generated for transient entities.
  • [WPF] EntityLink can now be used without breaking the designer.

v89.0.0

  • The.Generator has been replaced with The.Extension, a .vsix package. It's tested in VS2012, VS2013 and VS2015. The extension provides the same two commands as the addin did - 'Class Explorer' and 'Generate Code'. This change was initially motivated by the need to support newer VS versions but also allows us to add new features. Improvements so far:

    • you can debug the extension and templates with F5
    • code generation is now done in the background, using the status bar for progress display
    • runtime template errors result in a stack trace in the Output window, rather than a visual studio crash!
    • added a toolbar (right click on VS button bar and select toolbar 'The Framework')
    • added item templates for custom t4 templates and for new Model.xml files
    • added project templates for model/genonly projects The extension is available at \acdc\CodeGenAddin\The.Extension.89.0.0.vsix. It won't automatically uninstall the addin, so you'll have to get rid of it by hand at some point.
  • [MODEL] There's a new package The.Model, a shared dependency between The.Framework and The.Extension. This contains the bare minimum of code to read, write and template framework e/r models. Projects like Shobiz.CustomTemplates now only need to depend on The.Model, not The.Framework - but the major reason it exists is that VSIX packages include their dependency closure. Having The.Extension depend on The.Framework itself would have produced a 6 megabyte package containing half the contents of nuget.org.

    If we move to separate package versioning at some point then this would become the slowest-evolving package, the core of the whole thing.

  • [WPF] ValueReferenceFields, being disused, had accumulated some bugs - in particular, they couldn't safely be null.

v88.0.1

  • [WPF] Bugfix: SearchModal screens did not correctly bind ShowCriteria, which is shared with Search screens.

v88.0.0

  • Fixed packaging for The.Generator - it was omitting a dll.

  • [ORM] Entities now have a .report property. It's similar to .props, but returns a hierarchy of null-safe stringifying objects. You can write place.Inventories.Select(i => i.PlaceDescription.Name) regardless of whether place has any inventories or the inventories have any place descriptions - empty strings will be returned if any point in the chain is null.

  • [ORM] The.Reports contains a ReportManager module which does code generation and templating based on app-supplied model types. It covers three main use cases:

    Validate<T>(template) checks whether a template can compile and run for some model T Generate<T>(template, model) compiles and runs the template on an instance of T, producing output Precompile<T>(template) produces source code which can be used to run the template at a later date The template language is Razor, modified to detect RTF documents and take/produce relevant escape characters.

  • [ORM] Bugfix: Cloning a null or a value into a context which had acquired connections to entities not in the original context could create a bad 'half-cloned' state. The bug is now fixed for at least references; we need to investigate whether a similar one exists for collections.

  • [WPF] You can now inherit from the basic field types like The.WPF.Views.TextboxField and The.WPF.Models.BoundAttributeField<TModel,TView>, making it easier to create custom fields.

  • [WPF] Breaking: removed obsolete Loading properties from DisplayModalScreen and CreateModalScreen (use IsLoading instead).

v87.0.0

  • This release is about refactoring on the internal/external border, to both enforce and support global-free usage of the framework libraries. Much of this work was delayed until after the first release of shobiz, so there's a lot of stuff. Broadly speaking, all framework APIs are now available only through service handles, but these handles are provided whenever you're "in" the framework or have one of its context objects.

    A generator update is also required.

  • [ORM] IServices moved to the top level as The.Framework.IServices

  • [ORM] EntityContexts are now created by IServices.CreateContext() rather than new

  • [ORM] IServices is available from the public .Services on EntityContext, or as a protected .Services when inheriting EntityBase (or future base classes to come)

  • [ORM] A context is now required for all get and create operations on entities; for example, you must write Place.Create(c) or Place.GetByID(c, id). This allows the static api to be 'scoped' to a specific framework instance; it's now possible to have multiple separate instances of The.Framework in the same way that you already could for The.SQL. The major use case is safe concurrency and request-scoped instances in websites - but you could also do things like containing two different entity models in one application!

  • [ORM] The inconvenience of passing in contexts does allow for a few new commensurate conveniences in the API: .Clone() and .Copy() are now available in context-free forms, and .Delete() is back - but with new semantics, equivalent to EntityKernel.MarkDeleted(true).

  • [ORM] Generated IEntityInfo implementations are now singletons. They are not scoped to an IServices instance.

  • [ORM] PermissionSet has a new static method to form the set union of two PermissionSets.

  • [ORM] The 'DataThrottle' for document operations has been moved to SQLDocumentStore, where it's a constructor parameter maxSimultaneousDownloads. This is a perf optimisation specific to the SQL implementation.

  • [ORM] FileLogger can now only be created with TryCreate, not a constructor.

  • [ORM] Moved loose code into namespaces for internal organisation - The.Entities, The.ChangeTracking, The.Utility. If you're going to globally import a namespace in your application, The.Entities is the one - it has EntityContext, IEntity, IEntiyInfo, IEntitySet, etc. Previously, the idiom was to use it like The.IEntity because "The" is a) short enough to type, and b) too short to sensibly import - but this was inconsistent with the rest of the api.

  • [SQL] IServices moved to the top level as The.SQL.IServices

  • [SQL] IServices now exposes a DatabaseManager, which doesn't require extension methods like IDatabase does. The lower level abstraction is still available, moved to The.SQL.Database

  • [SQL] Composition.Builder allows you to override its IDatabase now (of course you could already do this by manually constructing a Composition.Root)

  • [SQL] Rather than exposing settings which can be used a by SQL____Store constructor but are otherwise extraneous, IServices now provides factory methods for the stores (including the document throttle, see above).

  • [SQL] Moved loose code into namespaces for internal organisation - The.SQL.Client, The.SQL.Documents, The.SQL.Persistence. Application code rarely needs to refer to them.

  • [WPF] IServices moved to the top level as The.WPF.IServices

  • [WPF] IServices now provides CreateScreen() directly rather than an IShell - IScreen is kind of the equivalent of EntityContext at this level. It might become a ScreenContext someday.

  • [WPF] IServices is available from the public .Services on IScreen, or as a protected .Services when inheriting ScreenModelBase, FieldModelBase, ControllerBase, LookupFactoryBase, CriteriaFactoryBase...

  • [WPF] Added convenience baseclass ModalControllerBase<TModel,TResult>

  • [WPF] Renamed controllers in accordance with the big model/view renaming that happened some time back - this entails dropping the "Entity" prefix from most of them

  • [WPF] Moved lookup types from The.WPF.Controllers to their own namespace

v86.10.5

  • [ORM] Bugfix: Copying an unloaded relationship would result in the copy's DataState incorrectly being Loaded instead of Creating, meaning that it would not be saved.

v86.10.4

  • [SQL] AsyncDatabase was failing to use ConfigureAwait(False), which could lead to main thread deadlocks.

v86.10.3

  • [ORM] Bugfix back-ported from v88.0.0: Cloning a null or a value into a context which had acquired connections to entities not in the original context could create a bad 'half-cloned'. The bug is now fixed for at least references; we need to investigate whether a similar one exists for collections.
  • [ORM] Bugfix: When cloning an entity into a context that contained a copy of that entity with less loaded references, this could cause a loss of updates to those references.

v86.10.2

  • [WPF] Bugfix: There was a race condition in ImageControl that could lead to a NullReferenceException being thrown if the Image property was set to null while a thumbnail was being loaded.

v86.10.1

  • [WPF] Bugfix: There was a race condition in TabController.UpdateCounts that could lead to errors being thrown if advanced criteria were added or removed during its operation.

v86.10.0

  • [ORM] A new overload of ImageProperty.Image.GetThumbnailAsync that allows specifying a target MIME type different to the source image's MIME type has been added.

v86.9.8

  • [SQL] Bugfix in automatic document compression, preventing corruption of data stored from >50MB non-seekable (non-file) streams.

v86.9.7

  • [SQL] Automatic document compression will now fail gracefully, falling back to the original document, if a) the compressed size would be greater than fifty megabytes (to avoid using too much client RAM) or b) compression fails in some other way.

v86.9.5

  • [ORM] Bugfix: FileLogger's logs were unreadable and frequently contained wrong stack traces.
  • [ORM] AttributeBase, when being saved or cloned, will now defer raising ValueChanged until the save or clone operation completes. EntityCollectionProperty and EntityReferenceProperty have not had the equivalent change made, but should sometime.
  • [ORM] Bugfix: BoundAttributeField, BoundLookupEnumCollectionField, BoundLookupReferenceField, CollectionSection, and LookupCollectionFieldBase now handle ValueChanged and SetChanged on the dispatcher instead of on the current thread.
  • [ORM] Bugfix: EntityList now handles ValueChanged on the dispatcher instead of on the current thread.

v86.9.4

  • [ORM] Bugfix: Cloning entities recalculates the calculated properties of those entities in the target context, but it was doing so in a flat loop without any dependency information, and so it could result in incorrect values if a persistent property - e.g. Text - depended on another persistent property. This was the cause of SB-2873.

v86.9.3

  • [WPF] List column layout has been improved, by removing the 'special' terminal column. This improves appearance and performance, removes scrollbar flickering, and fixes the crash bug SB-2869.

v86.9.2

  • [WPF] Bugfix backported from v90.0.3: race condition when loading a Content screen on a background thread

v86.9.1

  • [ORM] Bugfix: FileLogger would throw a NullReferenceException if there was a global method (i.e. a method without a class) in the call stack.

v86.9.0

  • [WPF] Bugfix: Lookup reference fields would always contain a hyperlink when read-only, regardless of whether they linked to reference data.
  • [WPF] Bugfix: Generated lookup fields were always writeable regardless of screen editability.
  • [WPF] NotificationObject.ExtractPropertyName has a new friend: ExtractPropertyPath, which generates an entire property path suitable for WPF data binding.
  • [WPF] EnumFieldBase has new overridable Choices and Selection properties.

v86.8.2

  • Bugfix: EntityCriteria could throw an InvalidOperationException if manipulated while it was updating counts or getting criteria.
  • Bugfix: the deadlock fix to Reify had broken context load-load conflict safety
  • Boolean list columns will now be displayed with "Yes" or "No" instead of "True" or "False".

v86.8.1

  • [ORM] Bugfix: GraphChecker would attempt to generate persistence operations for transient entities saved directly or via a context save.
  • [ORM] Bugfix: A deadlock could occur between EntityFactory.Reify and EntityContext operations.

v86.8.0

  • [ORM] EntityCollectionProperty, the non-generic base class, now has Add() Remove() and Clear() methods which can be used with IEntity arguments. The entities will be type-checked at runtime.

v86.7.0

  • Bugfix: The.Utility would throw a DirectoryNotFound exception when attempting to delete a nonexistent build staging directory.
  • [WPF] Criterion(Of T) now has a WithDefaultSubcriterion method that can be used to override the subcriterion that is used when the criterion is default and begins selected when the criterion is advanced.
  • [WPF] All nullable value-type attributes will now have a 'Has value' subcriterion generated.

v86.6.0

  • [WPF] ValueField(Of TModel, TView, TTraits)'s and ValueField(Of TModel, TView)'s constructors are now public.

v86.5.0

  • [ORM] AppDataPreferenceStore has a new Create factory method that handles and logs XML parsing errors. The existing constructor has been marked as obsolete.

v86.4.2

  • [ORM] Bugfix: WriteOneReadManyDocumentStore.GetImageMetadata threw an InvalidOperationException when the requested document was found in multiple stores.

  • [ORM] WriteOneReadManyDocumentStore better follows the emerging contract for IDocumentStore.GetImageMetadata:

    If you have the image, return its metadata and all of its thumbnails that you have (if any)
    If you don't have the image but have some of its thumbnails, return an ImageDocument containing only the thumbnails and ID = Guid.Empty
    If you have neither the image nor any of its thumbnails, return null
    

v86.4.1

  • [WPF] Bugfix: modal search screens were attempting to make a two-way binding to a read-only property.

v86.4.0

  • [WPF] DisplayModal and CreateModal screens were still Loading instead of IsLoading - now they have both.
  • [WPF] Excel spreadsheet output is now more closely matched to what Excel itself puts out.

v86.3.0

  • [SQL] There is once again a template for CreateTables.sql that creates tables without going through the identity column dance.

v86.2.0

  • [ORM] FileLogger has a new TryCreate method that will not throw exceptions. If it fails to create a valid FileLogger then

    it will instead return a NoLogger.

v86.1.1

  • [SQL] Bugfix: Entity sets returned by GetAll() were incorrectly comparing current-time-of-machine with current-time-of DB;

    if the DB server was even a microsecond ahead of the local system, this meant a race condition which could erroneously exclude just-created entities from the set. Some strange interactions with caching indicate that this may also have
    been responsible for the 'reference data cache nulls' bug we used to occasionally see.

  • [WPF] Bugfix: EntityList could crash when displaying an EmptySet<T> if a T was saved on another screen.

v86.1.0

  • [WPF] ExcelSpreadsheet has a new method ExtendConditionalFormattingTo(), which takes the template's conditional formatting range

    and moves it out to cover the specified row/column.

  • [WPF] Bugfix: ExcelSpreadsheet was stomping on template-defined styles.

v86.0.3

  • [WPF] Bugfix: write permissions were too strict for lookup reference fields; they now have the same requirements as lookup collection fields.

v86.0.2

  • [ORM] Bugfix: SecurityManager did not correctly track user switches (you'll like this one, Martin).

v86.0.1

  • [SQL] Bugfix: using an IQueryable<T:IEntity> to query t.Kernel.something was failing.
  • [WPF] Variable-size list cells have tooltips now.
  • [WPF] Bugfix: trying to 'copy cell' on the title column was crashing.

v86.0.0

  • [WPF] Bugfix: EntityList was initialising its row viewmodels on a background thread, which meant that row model

    overrides could trigger Dispatcher.VerifyAccess() crashes.

  • [WPF] Extracted export all the way out of list to an ExportManager on The.WPF.IServices, so that it can be used in other parts of shobiz.

  • [WPF] Property paths selected for export are now saved to a user pref, including their order.

v85.0.1

  • [SQL] Bugfix: the rename to EntityBase.kernel had broken SQL generation for properties like createdOn and modifiedOn.

v85.0.0

  • More export changes:

  • 'open after export' is on by default now, and maxLines defeaults to infinite

  • export is now available from screencommands on List screens

  • moved ExcelExportFormat to The.WPF, eliminating a dependency in The.Framework.

  • the spec for export is now a set of property paths, rather than individual properties;

    this allows you to export e.g. place.Inventory.PlaceDescription.PlaceName

  • the export options dialog used in lists (and in the new shobiz databrowser screen)

    gives you a tree view for exporting through relationships

  • Excel exports now use real Number/Date/etc formatted cells, with no need to convert

    (or possibility of a failed conversion)

  • added unit tests

  • [ORM] .Contains() has moved from IReadonlyEntitySet to IEntitySet, allowing IReadonlyEntitySet to become covariant.

    IReadonlyEntitySet<IEntity> is now a supertype of IEntitySet<T>, with obvious benefits.

  • [ORM] IEntityInfo has a new pair of sub/func visitor-Accept functions, allowing typesafe reification in generic code.

  • [ORM] After a long experiment with EditorBrowsableState.Never, entity.kernel and .props are now visible but lowercase.

  • [ORM] Removed the immediate .Delete() method on entities. For now, use entity.kernel.MarkDeleted(). At some future

    point, Delete() will be back but without immediate effect, just setting a mark; this change is deliberately breaking to ensure a safe transition.

  • [ORM] Bugfix: PreferenceManager.Flush would throw a NullReferenceException when it attempted to log an error.

  • [WPF] The non-generic IScreenFactory has been given the IEntityInfo visitor treatment, and its other methods have been removed - this type essentially existed solely to be unsafely cast to IScreenFactory<T>.

    Defining visitors for the common use case of operating on IEntity can be annoying, so there are a few predefined utility visitors in The.WPF.Controllers. This is similar to the previous convenience methods on non-generic IScreenFactory, except that you can write your own or take the simpler route of having an internal special-purpose Visitor implementation. Some use cases for casting to IScreenFactory<T> when you know T statically still exist. Suggestions for these appreciated- though what we really need, I think, is for a screenfactory to be supplied 'ambiently' to controllers when in a T 'context'.

v84.0.1

  • [SQL] Bugfix: SQLDocumentStore.GetBulkThumbnailData was including non-image files in the list of unthumbnailed images.

v84.0.0

  • Export reform:

  • set exporting moved to core from WPF. you can use .ExportAsync() on an IEntitySet anywhere

  • rather than separate frontend modules, export now takes in an IExportFormat. CSV and Excel formats are supplied

  • performance massively increased

  • export reports progress using an IProgress. in the wpf ui, this is handled by a loading bar and is responsive

  • list exports now consistently pick up set ordering, column selection and column ordering from the UI

  • [ORM] Bugfix: TimeProperty.Parse and NullableTimeProperty.Parse were accepting values outside the range of times storeable in a SQL

    time column, leading to an error when saving.

  • [WPF] One of the overloads of FieldModelFactory.CreateLookupReference has had an unused type parameter removed.

  • [WPF] The context menu items on FileControl and ImageControl are now disabled when the control does not contain a valid document.

  • [WPF] ValueReferenceField.IsEditable is now correct rather than always True

  • [WPF] Added LinkOrTextBox.IsEditable

  • [WPF] Bugfix: Conversion.String2TimeSpan and Conversion.String2NullableTimeSpan were accepting values outside the range of times storeable in a SQL time column, leading to an error when saving.

  • [WPF] Security: EntityLink controls in various places now have their OpenForEdit property bound appropriately to pick up

    access control, and in the fallback case will never open editably without checking access first.

  • [WPF] Security: You no longer need write access to the target of a lookup relationship in order to modify that relationship.

v83.0.0

  • Logging reform:

  • new namespace The.Logging

  • no need to manually specify linesOfStackTrace per-callsite anymore, this is now an implementation detail of the logger

  • speaking of which, it's called a "logger" now, not a "logging". the old The.Logging class is now The.Logging.FileLogger

  • there are now four log levels, defined in The.Logging.Level:

    Error: something is wrong and requires attention. Alerts that get sent to an administrator would be at this level.
    Warning: unexpected or undesirable behaviour. Should be reviewed but does not need immediate action.
    Info: recording of ordinary application behaviour. For logging events that are worth noting but not actually problems.
    Debug: info for developers only. Not compiled into release builds, so it can be high-volume.
    
  • loggers only have to implement one method, Write, and a manager class wraps different log levels. These now take consistent

    arguments - formerly, you could only supply an exception at Level.Error (or rather, with the old LogError)

  • errors displayed on WPF screens via IScreen.Handle are now also written to the log

  • rather than a special singleton, logging is now available from the framework composition root. provide/configure a logger

    using Builder.RegisterLogger() or in the constructor of Root, and you'll get IServices.LogManager.

  • [ORM] Removed DebugTimer, which is no longer used.

  • [ORM] Timed flushing and error handling have been moved to PreferenceManager - individual IPreferenceStore implementations don't have to worry about it anymore.

  • [ORM] Bugfix: ImageDocument thumbnails were not being picked up by the WORM store, resulting in their continuous recreation.

  • [SQL] SQL composition has been significantly simplified. Rather than pass flags to a magic constructor, you supply whichever IDatabase implementation you want, or provide an IAuthentication/ILogging to Builder to have it set up those features.

v82.3.0

  • [WPF] Criteria in searches are now totally isolated from each other - changes made to the spec in each custom criterion do not affect the specs in other criteria.
  • [WPF] AND, OR and NOT can now be used within a tab, chosen for each stacked criterion.
  • [WPF] Sections now have a context menu allowing the user to select Collapse All or Expand All.

v82.2.2

  • [ORM] Bugfix: AppDataPreferenceStore could, if saving took a long time, overlap itself and crash. The overlap has been prevented and errors become log entries instead of crashes now.

v82.2.0

  • [WPF] A CursorOverride module has been added to support more robust mouse cursor changes. If CursorOverride.Wait has been

    called at least once and the result not disposed of, then the cursor will be Cursors.Wait. Otherwise, if CursorOverride.AppStarting has been called at least once and the result not disposed of, then the cursor will be Cursors.AppStarting.

v82.1.2

  • [SQL] Bugfix: Syntax error in SQLDocumentStore schema

v82.1.1

  • [SQL] SQLDocumentStore now has a flag for documents that might benefit from being rechecked for compressibility. This flag will be set to on for existing rows when it is added to an existing database, but defaults to off for new rows.

v82.1.0

  • [ORM] Bugfix: PermissionSerialiser was reading incorrectly.
  • [ORM] Screen creation permissions are now enforced.
  • [ORM] Generated fields and sections of Content screens are now automatically hidden and/or made readonly based on permissions.

v82.0.0

  • [ORM] References to image thumbnails are now included in image metadata, reducing the number of database calls to check for existing thumbnails.
  • [ORM] IBulkDocumentStore now supports retrieving bulk data about which images have thumbnails.
  • [ORM] PreferenceManager is now IDisposable.
  • [ORM] PreferenceSerialiser now deals in PreferenceDictionary objects rather than plain dictionaries
  • [ORM] Added a similar PermissionSerialiser which gives you an in-memory format sufficient for implementing simple preference stores.
  • [SQL] SQLDocumentStore now uses less database roundtrips when storing documents.
  • [SQL] SQLDocumentStore can now store documents from streams that do not support the Length property (i.e. when CanSeek is false)
  • [SQL] SQLDocumentStore now compresses stored documents when they are not already known to be compressed and compression reduces their size by at least 10%.
  • [WPF] Added new subcriteria for whether relationships and strings are null/empty.

v81.0.1

  • [WPF] EntityLink's tooltip is now always equal to its displayed text.

v81.0.0

  • [ORM] Removed MEF usage entirely. The generated persistence classes are now provided to an instance of The.Framework using the RegisterMetadata()

    method, supplying (probably) the output of the generated Entities.CreateMetadata().

  • [ORM] Renamed IEntityInfo.SuperclassMetadata to .Superclass and removed .Subclasses.

  • [ORM] Removed public access to Composition.Root.Instance. It's still used internally for now, but we want to get rid of it at some point.

  • [ORM] Logging restructure begins: I've removed most functionality and cleaned up the rest a little bit. Redundant ErrorLogger is gone,

    the unused AppLog and its enum are gone, The.Logging remains but sans all its unused methods. I don't yet have a fixed idea of the 'right' way to supply a cross-cutting logger throughout the framework and applications, so opinions are welcome.

  • [SQL] Removed Composition.Root.Instance. Save your configured IServices in a global yourself if you really want one.

v80.0.0

  • [WPF] Lookup collections to reference data now use a resizable textbox.
  • [WPF] The auto-updating tag ui preference system has been moved from ValueFieldBase to FieldModelBase. Accordingly, FieldModelBase now requires a namespace parameter.
  • [WPF] Bugfix: MultilineTextBox had property order timing issues, and did not properly support IsReadOnly.

v79.0.0

  • This release includes a generator update.

    Automation changes: Using real semver means that it's no longer useful to do a build without incrementing the version, and it also makes it easier to manage tags, so:

  • version.bat, deploy.bat and zip.vbs have been removed. Their functionality has moved to The.Utility

  • build.bat has been split into test.bat and release.bat

  • each of release.bat and test.bat takes a version number argument. for test it must be a prerelease version; for build it cannot be

  • as well as building, release.bat creates a version number commit and a tag, and pushes packages and zips to their deployment locations

  • [WPF] FileControl and ImageControl have been rewritten to simplify them. They're faster now, and use fewer timers and threads; one of the benefits of

    this is that they no longer trigger a pre-4.5.2 WPF bug which was causing a crash when columns were removed from a list. However, they no longer support the .IsButton property.

  • [WPF] Lookup collections to reference data now use a new field type, an inline selector with a dialog box rather than a list.

  • [WPF] Lists now support right click->copy for cells and rows.

  • [WPF] Removed legacy Summary screen type and tabular list mode.

  • [WPF] Performance: RelationshipOptionsField now lazy-loads its choices set.

v78.1.2

  • [SQL] Version conflict checking can now handle nulls in modifiedOn.

v78.1.1

  • [WPF] Create and Display screens will catch WriteFailureExceptions containing SqlExceptions about unique key constraint violations and display a more friendly error message. This behaviour should be replaced with a more robust feature in the future.

v78.1.0

  • [WPF] SearchCommandOverride and SearchModeOverride are back and eager to prove themselves to a jaded audience.

v78.0.1

  • [ORM] Bugfix: RelationshipBase.RemoveAll(), used by EntityKernel.MarkDeleted(), did not work correctly in the presence of variously present state. This meant that any moderately complex deletion would fail.
  • [ORM] Bugfix: If entities A and B had two separate relationships to each other - e.g. Tree.Parent and Tree.Child being both the same - and both were altered in the same context, then they would not correctly save.

v78.0.0

  • [ORM] String trimming is no longer an implementation detail of The.SQL, and is implemented in the core. Of course, this raises certain questions...

    • why is it that we don't trim nullable strings? i've preserved this behaviour but cannot think of a reason.
    • why do we trim them at all??
  • [SQL] Removed MEF usage entirely. The generated persistence classes are now provided to an instance of The.SQL using the RegisterPersisters()

    method, supplying (probably) the output of the generated SQLPersistence.CreatePersisters().

  • [WPF] Un-autocompleteable text in AutocompleteText/Combo boxes is no longer a cruel, vicious red colour.

  • [WPF] Removed the SearchCommandOverride and SearchModeOverride properties for now, as they have a bug forcing all selectors into search mode.

v77.1.0

  • [SQL] Version conflict checking can now handle nulls in modifiedBy.

  • [SQL] Internal refactoring for slightly improved read/write performance (less memory/cpu used).

  • [WPF] By default, a criteria screen's default criteria will now be ordered by their properties' display order.

  • [WPF] Subtitle calculation for sections is now deferred until the rest of the screen has loaded. Lists have default subtitles

    based on their first few elements.

  • [WPF] Subcriteria search fields now have a clear button.

  • [WPF] EntitySelector's SearchCommand and SearchMode properties are no longer writeable, but it has new SearchCommandOverride and SearchModeOverride properties.

    This allows lookup reference fields' behaviour when the search button is clicked to be overridden.

  • [WPF] Bugfix: CollectionSection subtitles weren't updating when elements were added to or removed from the collection.

v77.0.0

  • The build system has been updated. Packages are now built from nuspec files, rather than just vbproj,

    and the 'fake dependencies' in package.config have been removed. These dependencies were used to specify dependencies for the built packages, but allow the use of project references during development. With nuget 2.5, the -IncludeReferencedProjects option makes that trick unnecessary. This change has a few benefits:

  • Package Restore workflows now worth with the solution (which is required for VS2015!)

  • We can more precisely control version numbers, using proper semver if we like

  • Built packages no longer include redundant copies of dependency dlls, reducing their size and reducing the possibility of type clashes

  • We could use advanced nuget features like click-through licenses in future

  • [ORM] New convenience methods on PreferenceSerialiser.

  • [ORM] VersionConflictExceptions now contain modifiedBy and modifiedOn info.

  • [WPF] IScreen.ShowNotification now has an optional 'details' parameter. The contents of this parameter are more technical than the 'notification' parameter and should be hidden behind a disclosure triangle or equivalent.

    ScreenExtensions.HandleErrors and friends will now include only the exception message in the main notification; the exception type and stack trace will be provided as details. VersionConflictExceptions caught by EntityCreate and EntityDisplay Save operations will now be displayed as a user-friendly message; the full exception will be provided as details.

  • [WPF] EntitySelector/ComboOrSearchBox, used for lookup fields, now includes a left-click set-to-null button. Previously, to clear the value, you had to right-click.

  • [WPF] Bugfix: The interaction between EntitySelector and BoundLookupReferenceFieldModel could create an invalid (un-saveable) entity graph.

  • [WPF] Bugfix: A redundant colon was being included in notifications raised from ScreenCommands.

  • [WPF] Bugfix: Image fields did not correctly trigger changedness/saveability if modified from a controller or viewmodel.

  • [WPF] Bugfix: Sub-search criteria were broken! They just didn't apply at all.

v76.3.0

  • [WPF] ImageControl and FileControl have a new IsButton property. Set it to false (it defaults to true) to disable the click-to-open functionality.

v76.2.0

  • [ORM] Added The.Preferences.PreferenceSerialiser which lets you implement IPreferenceStores using a common format.
  • [ORM] Added The.Security.PresetAuthentication as requested in THE-576.
  • [ORM] query.Take().ToSet() is now supported. (.Skip is still not supported)
  • [ORM] Bugfix: spec.SomeStringProp.Contains(null) was throwing exceptions in the wrong place.
  • [WPF] Added new field types: EnumField and NullableEnumField, for displaying a dropdown that picks from set options.
  • [WPF] Added preset date criteria - financial/calendar year stuff.
  • [WPF] Criteria auto-search timeout is now 500ms (up from 300).
  • [WPF] Performance: criteria/search screens now do more things in separate async tasks, in particular the updating of counts across the UI. This should remove the sequencing dependency in the degenerate case where a singular criterion adds a lot of in-DB overhead.

v76.1.2

  • [ORM] Bugfix: Excel/CSV export was exporting Date attributes with '12:00:00 AM' included.

v76.1.1

  • [WPF] Bugfix: ImageControls in list columns were not read-only.

v76.1.0

  • [ORM] Transient properties are no longer included in change descriptions.
  • [ORM] Bugfix: using .Not specs could generate incorrect sql for nullable dates, nullable datetimes, nullable booleans, nullable decimals, nullable currencies, nullable guids, nullable integers, nullable longs and nullable times (but not nullable strings).
  • [WPF] Popout text fields now wrap text. This can be configured with a checkbox which is saved to a user preference.
  • [WPF] Nonnullable string fields are no longer ever null.
  • [WPF] It's now possible to reset a string criterion by deleting the contents of the textbox.
  • [WPF] Added "Equals" criteria for strings.
  • [WPF] The default criterion for strings is now contains words, not contains phrase.
  • [WPF] Criteria now support an AppliesByDefault flag and .AsDefault combinator (for generated criteria). 'Default' criteria apply regardless of whether the user has changed them as long as their tab is 'active' (dirty). Additionally, they make the main tab itself always-active. These don't totally replace 'global' specifications - they may still work in tandem; for example, in shobiz, non-admins get an un-alterable global spec, and admins instead get a controllable default criterion.
  • [WPF] Bugfix: On multi-tab Criteria screens, the 'global criteria' are now applied separately to everything else in an explicit &&, meaning that it's a 'top-level' restriction on the whole specification. Previously it was an 'initial' restriction, which combined left-associatively with further booleans - an implicit INITIAL &&, which was incorrect under the presence of a later ||.
  • [WPF] Bugfix: Generated nullable boolean criteria didn't work if their default wasn't null.
  • [WPF] Bugfix: CreateModal screens would disable their create button as soon as a field became invalid, even though they weren't yet displaying invalidity.

v76.0.0

  • [ORM] Breaking: SpecialisedAttributeBase.TPresentation must now implement IComparable(Of TPresentation) so that in-memory sorting is supported.

  • [ORM] DocumentPresenterBase implements IComparable(Of T) by comparing OriginalFilenames when they are known.

  • [ORM] Entity specifications now support a .Matches(criteriaTree) criterion which splices in an entire tree.

  • [ORM] IsNull specifications return the right type. Previously you could not write this:

    spec.IsNull.And.SomeProp.EqualTo(50) because the IsNull returned a generic EntitySpecification<T> rather than the generated type with .SomeProp on it.

  • [WPF] Search screens now serialise their triggered searches so that old refreshes don't overwrite new ones. In related news, List

    screens go back to page 1 when you refresh, to be consistent with Search screens (which already worked this way).

  • [WPF] Boolean text display is now Yes/No/Unknown instead of True/False/Null, except in the case of exclusive choice (non-nullable) criteria

    which reads "Any" instead of "Unknown".

  • [WPF] Document and File properties now open their doc externally on a single click.

  • [WPF] Breaking: Collection fields can now be customised further: if you don't supply addEntity/removeEntity callbacks, that option is not available.

    This is a breaking change because the removeEntity parameter is no longer optional.

  • [WPF] Bugfix: calculated properties are now searchable.

  • [WPF] Bugfix: modal subcriteria did not apply if your WPM was too high.

  • [WPF] Bugfix: Controllers were subscribing to a screen's ScreenDisposed event before setting its content, sometimes causing that event to immediately be raised.

v75.3

  • [ORM] FileProperty.File.Upload will now make a basic attempt at sniffing the MIME type if it is not specified.
  • [ORM] Bugfix: ImageProperty.Image.UploadAsync was not correctly falling back to the file extension when MIME type sniffing failed.
  • [ORM] FileProperty.File and ImageProperty.Image now have static GetMimeTypeFromContentAndFileExtension methods that can be used to perform the same sniffing that Upload and UploadAsync perform.
  • [WPF] Bugfix: FileField and ImageField had a nonsensical ColumnDefinition width.
  • [WPF] When saving, FileField and ImageField will now suggest a file extension based on the MIME type if the original filename had no extension.

v75.2

  • [ORM] Added .Not to top-level EntitySpecifications - as well as spec.Age.Not.EqualTo(), you can now write spec.Not.Age.EqualTo().
  • [ORM] Bugfix: .EqualTo(string) and .In(T) specifications were incorrectly implemented and did not negate into a null check.

v75.1

  • [WPF] Fixed duplicate columns bug.

v75.0

  • [ORM] Bugfix: Specs of the form foo.Collection.AnyWith(subspec), where subspec was a conjunction or disjunction of multiple other

    specs, would produce incorrect LINQ along the lines of <q.Any(x => f(x)) && q.Any(x =>`` g(x))> rather than <q.Any(x => f(x) && g(x))>, and thus ultimately incorrect SQL.

  • [WPF] The TriStateChoice control has been renamed to ExclusiveChoice, and an InclusiveChoice equivalent has been added which provides checkboxes instead of radio buttons. The new control is used in search fields for nullable booleans.

  • [WPF] Added a new BooleanToBrushConverter.

  • [WPF] Bugfix: A bug which had crept into list UI allowed you to remove the first/text column, leading to a later crash. I've re-prevented removal of that column and added assertions to catch this case- saved prefs indicating to hide this column will also be ignored to

    prevent a recurrence of the crash for existing users.

v74.0.1

  • [ORM] Bugfix: Builder.Configure was trying to read from Logging.Instance before it was initialised.
  • [WPF] Fixed "Has value" subcriteria for dates (reversed not).

v74.0

  • [ORM] Application culture is now configurable in the composer via .WithCulture(). The default culture is en-AU with these customisations:

    .DateTimeFormat.ShortDatePattern = "dd MMM yyyy"
    .DateTimeFormat.ShortTimePattern = "HH:mm:ss"
    .NumberFormat.CurrencyNegativePattern = 0
    
  • [WPF] Breaking: Removed overridable CreateSpecification from generated criteria factories, replacing it with ApplyGlobalSpecification. This method will be called at appropriate times to set up criteria which should apply to all searches.

  • [WPF] Added generated relationship subcriteria factories; you can now write a GetDefaultCriteria() or GetAlternateCriteria() using an API

    of this form: yield this.SomeRelationship.SomeCriterion(s).

  • [WPF] Now that we have multicriteria, the criteria-adder list is a fixed, ordered one rather than showing only un-added options. The list

    still needs to be unique; criteria can now be re-labelled with .WithLabel.

  • [WPF] Unified the validation and conversion functionality into a namespace of functionality for dealing with primitive "Values", which

    might be reusable outside The.WPF. The "Traits" phantom types have moved from .Fields to .Values, and can now be used to specialise conversion as well as templating.

  • [WPF] Currency fields use now this system instead of a custom field type, preventing undesirable WPF conversion enforcement.

  • [WPF] Added "Has value" subcriteria for dates.

  • [WPF] Bugfix: the column context menu did not display on many lists.

v73.0

  • [ORM] BREAKING: Instances of The.Logging are now created by calling The.Logging.TryCreate instead of by using its constructor; if this fails to create a usable instance then null will be returned instead. If this happens then another implementation of ILogging (e.g.

    NullLogging) should be fallen back to.

  • [ORM] Optimisation: needless 1=1 nodes stripped from criteria tree

  • [ORM] Optimisation: .StartsWith and .EndsWith specs now translate to String.StartsWith and String.EndsWith lambdas, and therefore to SQL LIKEs rather than SUBSTRING functions, which can use indexes.

  • [ORM] Bugfix: The.Logging was using naïve string concatenation to build file paths, causing files with names like 'LoggingFramework.txt'

    to be created in the wrong directories.

  • [SQL] Bugfix: .Any() subprojections materialised into EntitySets could produce a ResultSet with a bad Count, containing duplicate ids!

  • [SQL] Bugfix: the query idiom "x => Not x.Any(f)" was translated incorrectly, as if it had been written "x => x.Any(Not f)".

  • [WPF] BREAKING: The.WPF has a bunch of search-related functionality that isn't MVC, now - it's moved into namespace The.WPF.Search.

  • [WPF] File- and ImageControls will now log errors caught from attempting to display files and images rather than ignoring them.

  • [WPF] Search criteria can now have optional 'default' values. In main tabs (only), these values will be pre-entered into the fields, immediately restricting the search results via the paired specification.

  • [WPF] BoundAttributeField's constructor is now public. Do not use it frivolously!

  • [WPF] Bugfix: the entire main search tab did not work (e.g. did not contribute to search results).

v72.0

  • This release comes with an addin update.

  • [MODEL] Added 'AdminOnly' flag for columns. ShowOnForm/InList/InSearch flags control whether an attribute is displayed

    by default; users can still add non-ShowInList columns, for example, to a list. With this new flag, non-admin users will not be able to add those columns. This is intended for use for 'internal' or 'technical' properties, which are not meant to be user-visible or editable data.

  • [ORM] .IsAdminOnly is available on AttributeInfo.

  • [TEST] Removed The.Test.Mocks package - it was poorly isolated by nature, impossible to use with PCLs. Instead, each mock is now defined at the top level of its transitive closure.

  • [WPF] Runtime checks for AdminOnly prevent columns from being added to lists or as search criteria. Since we don't have

    a fixed definition of an 'admin' yet, the columns are never addable.

  • [WPF] More subcriteria added.

  • [WPF] Subcriteria selector/indicator removed from the basic criteria group.

  • [WPF] Removed counts from empty relationship-selector criteria.

  • [WPF] Bugfix: search screen comboboxes were staying open too long.

v71.0

  • [WPF] Breaking: Search criteria have been upgraded to 'multicriteria'. The new template "Criteria.tt" defines multiple

    subcriteria for different ways to match on builtin types, and the Criterion.Create() API has been similarly upgraded. Any criterion that has multiple subcriteria now displays with a drop-down menu, allowing the user to select which kind of search to perform. Numerous new search field types are available, including more Ranged field types.

  • [WPF] Bugfix: Display screens were remaining in the 'loading' state after a save operation failed.

  • [WPF] Bugfix(?): The various circular buttons on Search screens had weird two-pixel-tall green rectangles on their left sides.

v70.0

  • [ORM] Reference Properties now have a ValueChanged event, similar to the ones on Attributes.

  • [WPF] Lookup Reference Fields use the new ValueChanged event to update the UI if the underlying model changes. This is relevant if some other field sets a reference, such as the shobiz CorrIn File suggestion system.

  • [WPF] The initial/title column in lists is now named after the entity's caption.

  • [WPF] Breaking: New screen type 'Criteria'. This is used in Search and SearchModal screens, but can also be used standalone to provide a

    way to pick a set of entities.

  • [WPF] Using Criteria screens, there are now search criteria generated for all relationships. Relationships to reference data use

    the existing checkbox-selection dialog, and relationships to nonreference data use a set of search criteria. The implementation isn't particularly optimised; in particular, it involves storing a list of matching IDs in memory. It would only take a moderate amount of work to improve this to work by ICriteriaTree splicing, but it doesn't seem to be necessary yet.

v69.0

  • [WPF] SingleLineConverter now replaces line breaks with spaces instead of simply removing them.

  • [WPF] Breaking: Content screens now have a new argument, useSectionPreferences, and sections have a usePreferenceBasedExpansion

    constructor argument. These are used in tandem by the generated viewmodels to have Create screens expand all their sections by default.

  • [WPF] Breaking: Removed Models.SearchScreen.AllowShowTabs.

  • [WPF] Bugfix: SearchModalScreen was displaying tabs incorrectly.

v68.4.1

  • [ORM] Experimental 'bug'fix(?) - relationships less strict about repeated mutation.

v68.4

  • [WPF] Display screens now notify content screens when they've been saved, allowing HasChanges to correctly reset.

v68.3

  • [WPF] Section visibility can now be specified as a predicate with .VisibleIf()

v68.2.1

  • [WPF] Bugfix: ModelSection did not ever work.

v68.2

  • [WPF] Decimal fields now convert to string using format 0.#, rather than whatever the default is. This means that

    e.g. decimal 8 will no longer display as "8.0".

v68.1

  • [WPF] Custom search screens can now toggle display of the 'show tabs' button with the view model's AllowShowTabs property.

v68.0

  • [ORM] Search specifications can now provide the underlying ICriteriaTree, a lower level abstraction. The newly public ICriteriaTree is an immutable tree of symbolic propositions in a multivariate boolean algebra; trees can be created out of DelegateCriterion

    objects, combined with .Disjoin() .Conjoin() and .Negate() operators, projected to search through relationships by the Select() operator, and projected to a final predicate form with .Project(). A .Not() operator has been added to specs; it works like .And() and .Or(), either producing or consuming a subspecification. All the predicates now provide an inverse form, hardcoded to support potential implicit nullability and criteria tree folding optimisation. .NotEqualTo() and .NotNull() predicates have been removed as redundant. Some predicates have also been shuffled around: .IsNull() is now available on all specifications, purportedly-nullable or otherwise.

  • [WPF] Search screens now use a tabbed criteria system; you can use the (<) button to break out some tabs for AND, OR and NOT subspecifications.

    They're executed with implicit parentheses, and can be rearranged to change the ordering. Only tabs with some entered criteria affect the final result or contribute to the running subtotal.

  • [WPF] BREAKING: Removed the ability to parameterise Search screens with a custom ICriteriaFactory. This caused more problems than it solved, and would not have worked with upcoming sub-search functionality.

v67.1

  • [ORM] PersistenceManager will now throw the new ConnectionException instead of ReadFailureException or WriteFailureException when the persistence store cannot be reached.

v67.0.1

  • [SQL] DocumentMetadata's thumbnail indexes now include only rows that are thumbnails.

v67.0

  • [DOCUMENTS] There is a new IDocumentStore implementation: WriteOneReadManyDocumentStore. This reads simultaneously from multiple IDocumentStores but writes to just one.
  • [SQL] SQLDocumentStore's tables now have primary keys and DocumentMetadata has indexes for retrieving thumbnails more efficiently.
  • [SQL] BREAKING: SQLDocumentStore must now have an IDatabase injected; it cannot create one itself.
  • [SQL] You can now get a SQL script that creates the schema for a SQLDocumentStore by calling the static SQLDocumentStore.GetCreateSchemaSql method.

v66.1

  • [WPF] UserFields now have the left-alignment fix.
  • [WPF] The Search criteria expander now has a top line as well as a bottom one, to differentiate it from the title section.

v66.0

  • [ORM] Parts of the dynamic internals of The.Persistence have now been exposed for efficient low-level code. New public methods:

    PersistenceManager.GetAll : ReadOps.IResultSet
    PersistenceManager.GetByID : ReadOps.IResult
    
  • [ORM] Newly public classes:

    EntityFactory - transforms IResults into typed IEntity + EntityKernels in a Context
    SyntheticResult - an IResult implementation representing a cached entity or an entirely fake one
    StreamingResultSet - IEntitySet implementation; requires a Context and an IResultSet; streams pages directly from the database
    ConcreteResultSet - IEntitySet implementation; requires a Context and an `IEnumerable<IResult>` (like you get from IResultSet.StreamPage)
    
  • [SQL] Queries now have support for .Equals(), e.g

    from x in Entity.Query()
    where x.Foo.Equals("bar")
    
  • [WPF] Expanded search criteria system, replacing 'advanced' mode with add/remove of any criteria from the available basic+advanced set.

    It displays running counts of the search results for each added criterion. There's a new theme key, CriteriaCountWidth, for this, because the expected number of search results is pretty application-specific.

  • [WPF] Field content is now left-aligned rather than centered if allocated more horizontal space than its MaxWidth.

  • [WPF] Renamed screen views to match the model renames in the last release.

v65.0

  • [ORM] CSV and Excel export bugfix - un-loaded relationships were not being exported.

  • [WPF] Search and SearchModal screens can now be given CriteriaFactories directly at creation to override the MEF-resolved instances.

  • [WPF] Transient but non-Abstract entities now have CreateModal screens available.

  • [WPF] Added a special field type for nullable strings, with a checkbox.

  • [WPF] Added ranged criteria fields, generalising the TwoDatesField into RangeField(Of T). Currencies search criteria are now ranged.

  • [WPF] ISectionModel now exposes its collection of fields.

  • [WPF] BREAKING: Added SectionHeaderWidth theme key.

  • [WPF] BREAKING: Removed IBoundFieldModel :)

  • [WPF] EXTREMELY BREAKING: Some model types have been renamed to be consistent with the rest of the dll. In general, all models and views are now named <Something> if they're a plain IModel, or <Something>Field/<Something>Screen/<Something>Section for IFieldModel/

    IScreenModel/ISectionModels.

v64.2

  • [ORM] EntityBase.Equals() is now more correct - it could occasionally have false positives.
  • [ORM] Calculated strings are now trimmed like persisted strings.
  • [WPF] NeedsSave separated from HasChanges in display screens; the former ignores calculated and transient properties.
  • [WPF] Expanded export options dialog.
  • [WPF] Added a horizontal scrollbar to pop-out textboxes.
  • [WPF] Text criteria fields use a one-line textbox.

v64.1

  • [SQL] Bugfix: QueryTranslator was generating empty strings (instead of e.g. '1 = 1') for Boolean constants.
  • [WPF] Search and SearchModal screens can now be given CriteriaFactories directly at creation to override the MEF-resolved instances.

v64.0

  • [WPF] Added an additional optional parameter to ValueCollectionModelBase to allow overriding the default DoRemove behaviour.
  • [WPF] Changed Sort Default to Text
  • [WPF] Bugfix: theme brushes ListCellSelectedForeground and ListCellSelectedInactiveForeground will now be audited.
  • [WPF] BREAKING: There is a new theme style for the ColumnPanel in RelationshipOptionsDialog: RelationshipOptionsColumns.
  • [WPF] Generated criteria factories will no longer yield criteria for relationships to non-reference data. These criteria will still be generated for overriding subtypes to use.
  • [WPF] RelationshipOptionsDialog options will now be sorted by their Text property.

v63.2

  • [WPF] New "RelationshipOptions" field type, which allows selecting one or more entities from a set.
  • [WPF] Added generated search criteria for all navigable relationships.
  • [WPF] Bugfix: sorting by relationships was broken.

v63.1

  • [ORM] .Copy() is now available on abstract entities.

  • [SQL] In order to support new advanced search features, LINQ 2 Definite Articles has been expanded. The dynamic sql generator now

    supports the following additional use cases:

    • Joins are now individually tracked, allowing queries which join to the same table multiple times for entirely different purposes, such as ANDed mutually exclusive search conditions or a sort (inner join) by something which may be null (outer join).
    • <search-condition> and <row-value-constructor> grammars are now fully separated, allowing queries which require contextual treatment such as the distinction between .Where(f => f.SomeBool) and .Where(f => f.SomeBool != SomeOtherBool).
    • Projections via the Select and SelectMany operators are now available - the major limitation is that you have to project to entities, not attributes. So .Select(e => e.SomeEntity) or .SelectMany(e => e.SomeEntity.SomeEntities) are ok, but not .Select(e => e.SomeAttribute). Attribute projection support could be added in another refactoring pass if we need it.
    • string.StartsWith is now supported (this one snuck in because some pre-written tests were expecting it).

v63.0

  • [ORM] BREAKING: The.Logging is now a singleton rather than a (pseudo-)module. All calls to The.Logging should be updated to call The.Logging.Instance.
  • [WPF] BREAKING: There are two new theme brushes: ListCellSelectedForeground and ListCellSelectedInactiveForeground.
  • [WPF] EntityListRowBase now has an IsSelected property.

v62.1

  • [ORM] Persistence now has an exception contract. It should only throw WriteFailureException, ReadFailureException or VersionConflictException.

  • [ORM] Continued relaxing query-side context input requirements.

  • [SQL] Version conflicts are now allowed if the overwrite was by the same user within a configurable timespan.

  • [WPF] New list editability heuristics implemented:

    If an entity has <= 3 ShowOnForm properties and 0 ShowOnForm Value relationships, it is *inline*. An IsInline, IsEditable list is edited inline, with fields, rather than having to open it up. Both properties can be set separately. IsInline, regardless of editability, also controls two other aspects of list display: it suppresses the 'title' column, and turns even immutable references into hyperlinks.

  • [WPF] New default pagesizes: Field lists - 5; Modal searches - 10; Modeless searches (and thus Index screens) - 20.

  • [WPF] Rewrote the date-range "TwoDates" search criterion to fix bugs - it wasn't triggering auto-search, and didn't

    behave reasonably if you set only one date. It also now provides a caption which explains what exactly you are searching for.

  • [WPF] Added a new Creating/OnCreating event to Content screens, which is raised once when the screen is first

    initialised with a to-be-created entity.

v62.0.2

  • Increase concurrency detection robustness - now works with arbitrary triggers and cascades.

v62.0.2

  • Make concurrency detection work correctly with the reference data cache.

v62.0.1

  • Bugfixes for the new persistence.

v62.0

  • [ORM] BREAKING: AboutToSave renamed OnSaving.

  • [ORM] Persistence refactored to formalise it as a series of passes over the entity forest. This means that dependencies

    between the various stages of saving are now explicit and allowed. Calculated properties can be dependent on autonum prediction; OnSaving can be dependent on both autonum prediction and on calculated properties.

  • [ORM] The persistence layer now detects concurrent modification and deletion, and throws an exception rather than overwrite

    the data. The major limitation is that it detects only changes to entities, using the version attribute, and so it won't pick up relationship changes.

  • [ORM] Bugfix: BLOB property comparison was totally wrong for nontrivial cases, which was kind of disastrous as assignment

    also depends on comparison.

  • [WPF] MultilineTextBox now has a Label property which is used as the ScreenTitle for the modal dialog it displays.

  • [WPF] Lists can now be exported to Excel as well as CSV (though as with any office interop, it's a somewhat fragile process).

  • [WPF] New "LinkOrTextBox" control, used in EntitySelector and LookupReferenceField to provide an EntityLink container which is visually consistent with text entry controls. In particular, immutable nonenumerated lookup references are now hyperlinked.

  • [WPF] Bugfix: MultilineTextBox's modal dialog wasn't respecting the IsReadonly property of the MultilineTextBox itself.

  • [WPF] Bugfix: Create screens' Save command wasn't correctly async-awaited, so its errors could get lost.

  • [WPF] Bugfix: EntityLinks inside EntitySelectors were picking up the DoOpen command of containing EntityLists.

v61.0

  • [ORM] Bugfix: EnumerationCachePolicy.Visit(InsertRelationship) was throwing a KeyNotFoundException in certain cases.
  • [ORM] Check MaxLength on calculated properties
  • [WPF] All FieldModels now depend on an IScreen. As such, they're now able to do things like show modal dialog boxes.
  • [WPF] MultilineTextBox now has a button to open a modal dialog for editing its text.
  • [WPF] There's now a style in the theme for the ColumnPanel displaying search criteria.
  • [WPF] Add search refresh to the criteria reset command

v60.1

  • [ORM] CSV export will now replace common unicode characters such as "smart quotes" with ascii equivalents
  • [ORM] AboutToSave really added
  • [WPF] The Models.tt template will no longer throw an exception (crashing Visual Studio) when two collection fields have the same caption. Instead, one of the fields will arbitrarily be selected as 'the' collection for the generated section.
  • [WPF] PropertyChanged when setting commands

v60.0

  • [ORM] BREAKING: IPreferenceStore now has a TryGetValue method instead of ContainsKey and GetValue. It also has a Clear method.
  • [ORM] AboutToSave added
  • [WPF] Hyperlinks will not be blank even when text is null

v59.0.3

  • [WPF] Bugfix: live-search was breaking on criteria reset.

v59.0.2

  • [WPF] Added a bit of a gutter to the criteria columns on Search view.

v59.0.1

  • [WPF] Replaced the search button on Search screens with "live" search - after a criterion field is modified, after a 300 ms delay, search occurs. If you keep typing, the 300ms timer is reset until you stop.

v59.0

  • [WPF] ScreenModelBase is now a little friendlier - if you fail to set .Commands it isn't a bug.
  • [WPF] Modal screens now return (a task of) ModalResult<T> instead of T - making cancellation explicit.
  • [WPF] Instead of .WithLabel(string), ISectionModel now has .WithTitle(string) and .WithSubtitle(string). The subtitle is displayed separately and calculated live (as long as it depends on fields within the section).

v58.1

  • [ORM] .Query() methods on entities and specs can now be called without a context, in which case they create a new one. Context merging is safe and fast enough now that this is ok - it's not a return to the older style of "contextless" entities, which are still only possible for newly created ones.
  • [ORM] PropertyInfo now has a DisplaySection property.
  • [WPF] Models.EntityContent subclasses now have a GetSectionDefinitions() which returns the contentsectiondefinitions as originally provided, for reconstructing and wrapping.
  • [WPF] Bugfix: editability of list rowmodels no longer gets out of sync with that of the list.

v58.0

  • Composition reform continues. Each module now has in its Composition subnamespace a Builder, a Root class, and an IServices interface which the Root implements. Roots might also have additional functionality, like test functions or IDisposable. Using the Builder class (formerly ConfigBuilder) produces a Root, which is essentially "an instance of the framework".

    The services formerly available as globals on *.Composition.Root are still temporarily available via the .Instance singleton - so an IDatabase, for example, can be obtained from The.SQL.Composition.Root.Instance.Database. As well as being alarmingly long, this will eventually be removed. The way of the future is fully nonstatic composition, but we're still in the present today. To access various framework services (security manager, preferences, documentstore, whatever) IServices implementations are or will be provided to overrides and hooks. For example, the InitialiseModel method of ControllerBase subclasses gets this context, as do Content model overrides, and IModelFactory. The IServiceses, which need better names, are analogous to the HttpContext in ASP.NET or ServiceContext in WCF. Various services are moving around as part of this. Notably, PreferenceManager and the new PersistenceManager (combines functions of GraphReader and GraphWriter) are now available rather than the underlying I___Stores, and they're instanced rather than global modules.

  • [ORM] Fixed NTLMAuthentication, again.

  • [SQL] Auditing is now optional.

  • [WPF] Screen Commands no are longer in an ObservableCollection, because they can no longer be changed piecemeal - the IScreenCommand.IsVisible feature replaces this functionality.

  • [WPF] SearchModal screens now let you select something by double-clicking on the list or selecting a hyperlink in the list, as well as by explicitly activating the Select button.

  • [WPF] List screens can no longer be inline-editable if the entity has properties which cannot by displayed inline, and their title/link column is now frozen.

  • [WPF] Create screens (both modal and modeless) will not show their validation errors until the user clicks "Save" or "OK". Accordingly, the "Save" or "OK" button will not be disabled until validation errors are visible.

  • [WPF] Bugfix: the generated criteria factories were miscompiled by VS2012. Rearranging methods has 'fixed' this.

v57.3.1

  • [WPF] ListSelectionDialogs created from an EntityList will now sort the available fields by caption.

v57.3

  • [WPF] New SelectionChanged event on EntityList models no longer crashes, also it's called EntitySelected.

v57.2

  • [WPF] New SelectionChanged event on EntityList models.

v57.1

  • [WPF] Made custom screen creation more convenient, with a ModelessControllerBase which takes less type parameters and has an IsOpen property.

v57.0

  • [ORM] We had basic support for setting relationships during property calculation, but there were too many edge cases, so this is unsupported for now. The API hasn't changed, but several tests have been removed and the functionality won't be maintained! Don't do it please!
  • [ORM] The error message produced for unimplemented calculated properties in override classes is now less friendly, but more polite.
  • [ORM] Bugfix: cloning graphs created a subtly wrong relationship state, where relkernel pairs were no longer reference-equal - each entitykernel had its own! This was ok for most navigational purposes, but created an error if a 1:m relationship was newly added, then cloned, then saved twice. This pattern of behaviour became common once CreateModal began prospectively attaching its new entity in a subcontext and then cloning back, and is therefore responsible for quite a few reported SHOBiz issues.
  • [WPF] Collection relationship fieldmodels now take more parameters and less closures, for easier hand-construction - this reduces flexibility in order to guarantee feature support. For example, they now have builtin security checks, and fully overridable button text.
  • [WPF] Exposed the generated IScreenFactory<T>s singletons statically, as <gen>.Controllers.<foo>Factory.Instance. Something like this may be the future of IEntityInfo, or vice versa.
  • [WPF] Drop-down comboboxes can now be cleared by pressing delete, or backspace, or with a context menu.
  • [WPF] Collections and comboboxes now follow the same validation-exemption logic as attributes: if they were loaded into the form from the database, the value they had in the DB is considered Valid even if it would not have been valid if newly entered by a user.
  • [WPF] NotificationManager methods NotifyEntityOpened, NotifyEntitySaved and NotifyUIPreferenceChanged are now public.
  • [WPF] Bugfix: calculated attributes were not raising ValueChanged when they were recalculated as part of a save, even if they had changes.
  • [WPF] Bugfix: only some newlines were stripped from text displayed in columns.

v56.0

  • [ORM] Diagnostics have been added to the reference cache to try and track down THE-588. Please let me know if you see an assert!

  • [ORM] Bugfix: No more null MemoryStreams in documents.

  • [WPF] ISectionModels can now be resizable. CollectionSection has been made resizable, with the size saved to the preference manager.

  • [WPF] List editability heuristics have been expanded. Here's the new rule:

    If a list has <= 3 default columns, it's _small_. Lists display link/title columns unless they are small. Lists cannot be editable unless they are also small. What this means in practice is that immutable value collections which would not have had a title column if they were editable now do not have it regardless of their editability.

  • [WPF] Security: Search screens now correctly make their internal Lists non-OpenRW if necessary.

  • [WPF] Bugfix: The Create buttons on CreateModal screens were not made immediately-active if the new entity was already ready to go. Now they are.

  • [WPF] Bugfix: There were some corner cases where attribute fieldmodels did not raise propertychanged for certain things. In particular, if you bound an attribute to a field and then updated the attribute via setting the entity's property code, and this caused its validity as determined by a viewmodel override to change, the GUI did not update the enabledness of buttons to reflect this, although the actual value and the validation UI appeared to change. Now it works.

v55.0

  • [ORM] Expanded security framework - IAuthenticationManager and IAuthorisationManager replace ISecurityContext; they deal in Subjects and Operations, which combine a Subject and an Object with a Permission. The higher level SecurityManager, accessible from The.Composition.Root, provides a caching API.
  • [ORM] File attributes now infer MIME types from upload filenames.
  • [WPF] Screen-level security using a precondition paradigm; each screen must only provide UI access to commands which check successfully. In debug mode, creation of controllers will validate these preconditions. A SecurityManger instance is provided to all controllers and to content overrides, allowing them to make decisions about which facilities to provide.
  • [WPF] ScreenCommands now have an IsVisible property, which does what you'd imagine.
  • [WPF] CreateModal screen title is now consistent with Create - "New <entity>".
  • [WPF] ComboOrSearchBoxes in search mode now have a hyperlink to allow you to open the selected entity.
  • [WPF] Bugfix: IFieldModel.Immutable() no longer prevents a field from providing change notifications to the UI.

v54.0.1

  • [ORM] Fixed NTLMSecurityContext (now NTLMAuthentication) - it'd broken when using nonstatic composition because some magic never took place.
  • [WPF] Text containing carriage returns no longer causes list rows to grow in height.
  • [WPF] Validation messages now refer to properties by caption rather than name.
  • [WPF] Search screen criteria may now be collapsed.
  • [WPF] Change description for files and images should have less information but be more user friendly now.
  • [WPF] The Pager control will now respond to its available size.

v54.0

  • [ORM] Bugfix: persistent calculated properties which were dependencies of other calculated properties could, during save, be calculated insufficiently early, leading to not all objects in the graph being saved - this was causing more and more issues in shobiz over time, related mostly to Text.
  • [WPF] Files now show in lists. There are new ListFile and FieldFile Styles. Use MaxHeight on these styles to limit the size of the FileControl's icon.
  • [WPF] Bugfix: the title column of lookupcollection lists could vanish if the viewmodel was rebound to a view (as in the shobiz tab-pinning system).
  • [WPF] Bugfix: search screens' Refresh command was not marked as a refresh command.

v53.0

  • Plugin selection and config is now done in code rather than using IProvider and magic app.config settings. Use an instance of the ConfigBuilder classes in the various .Composition subnamespaces to configure each component you're using with a fluent API. This reduces dependence on static composition considerably - it's now more feasible for applications to do their own or to use a DI container other than MEF. More changes will be coming, hopefully removing MEF entirely at some point. All appSettings have been removed and are now supplied via the ConfigBuilder system instead, including the LogXXX flags.
  • [ORM] New app setting: LogCloning, does what it says.
  • [ORM] Extremely large Clone performance improvements.
  • [WPF] Added a new ISectionModel, ModelSection - this adapter wraps an arbitrary IModel in a collapsible section.
  • [WPF] Replaced ScreenField with ModelField in a similar vein. FieldModelFactory has both CreateScreen and CreateModel functions, if you're using that to create them.
  • [WPF] Bugfix: Modeless Create screens were titled using entity Names instead of Captions.

v52.1

  • [ORM] Bugfix: collection contents updated via cloning didn't raise SetChanged since v50 or so. This was causing additions to Value Collections in the gui to apparently fail - it did not update the display.
  • [WPF] Create and CreateModal are now "real" screens, not variations on Display, and can be separately overridden. This enables, for example, the substitution of wizards for forms for a given entity.
  • [WPF] IScreenCommand now has an .ExecuteAsync() function for tests and automation - use this in preference to executing its .Command member.
  • [WPF] In Lists with a link/title column, clicking it will now sort by Default Ordering Attribute rather than Text.
  • [WPF] Content sections named for and containing a collection field will use a special CollectionSection to keep their label updated based on its count.

v52.0

  • [WPF] Removed the "content size group" feature of fields. This is no longer necessary with the grouping provided by Sections, and the grid usages it necessitated were causing problems in other areas of the UI. Grid.SharedSizeGroup is quite buggy and makes it impossible to achieve certain autosizing layouts. Among other things, this improves layout performance and fixes the too-narrow fields observed on shobiz Search screens.
  • [WPF] FieldModelFactory.CreateNullableBoolean() now accepts arguments to override the text representing True/False/Null values.

v51.1

  • [SQL] The generated CreateIndexes.sql will no longer create foreign keys for the join tables of legacy-only relationships, and will drop these foreign keys if they already exist.
  • [WPF] EntityDisplay.Save() now does its work on a background thread with a progress bar, responsive UI, etc.
  • [WPF] EntityDisplay.Refresh() asks the user if they're sure that they want to discard changes.
  • [WPF] Lookup collections of reference data no longer display hyperlinks, only names. When creating a List screen you can optionally specify whether it's a lookup.

v51.0.1

  • [SQL] Bugfix: DEFAULT values were being generated for timestamp/rowversion columns, which is not allowed by SQL Server.

v51.0

  • [ORM] Fixed some obscure but severe relationship bugs: clones of collections which had been remotely modified without being loaded, if not themselves loaded or saved, could not be cleared; shallow copies weren't; reentrant cloning was safe, but extremely underperformant.
  • [SQL] Nullability rules improved: nullable columns in nonnullenforcing databases are now correctly undefaulted; nonnullable dates and times in such dbs now default to 1/1/1800 instead of "something".
  • [SQL] Audit triggers were being generated for transient properties.
  • [WPF] Opening entities from lookup collections will now bring them up in a modeless screen (in shobiz, a tab).
  • [WPF] Removed obsolete "name" field from ContentSectionDefinition.
  • [WPF] ISectionModel.WithName() has become .WithLabel() to better reflect its function.
  • [WPF] List column headers now have a tooltip.

v50.0.1

  • [SQL] Bugfix: audit triggers were being created for Transient entities.

v50.0

  • [ORM] Change description seems to have Unicode in it now.
  • [ORM] Roundtripped Double preferences are now supported.
  • [WPF] List inline editability is now determined by the number of ShowOnForm properties, not the ShowOnList properties. The rationale is that inline editing is only warranted for entities which would otherwise be trivial, pointless forms.
  • [WPF] List column ordering is now saved as a user preference.
  • [WPF] Content sections created by model overrides can/must now have a DisplayOrder specified.

v49.0

  • [ORM] Relationship semantics: .Copy() is shallow with respect to value relationships, but purported to deeply copy lookups. In reality, this is only feasible when the other side of the lookup is a collection; bugs were making copies of lookups-to-references appear to succeed, but they'd created a corrupt data structure which could not be successfully saved. Copy() will no longer attempt to copy any relationships other than those which are .IsLookup to .OtherSide.IsCollection

    This has a limited impact in SHOBiz as all of its lookups have collections on the other side.

  • [ORM] Bugfix: Adding a relationship to a reference to a collection and then removing it again would result in the reference still HasChanges()ing.

  • [SQL] Inheritance support added to EnableIdentityColumns.tt

  • [WPF] List editability is now based on the number of modelled columns in the list, not the user's preferences - so if they remove almost all of a noneditable list's columns, that doesn't make it editable.

  • [WPF] Search criteria are now displayed in a ColumnPanel! ColumnPanel rules!

  • [WPF] LookupCollection fields now update their dropdown, if there is one, so that it only displays options which have not already been added to the collection.

  • [WPF] File fields now display an icon and have options similar to Image fields/controls.

  • [WPF] SQL errors while loading list data for collection fields are now displayed - a bug was causing them to be discarded, which also hurt performance.

  • [WPF] Fixed crashes when ColumnPanel width was 0 and when it had 0-height elements.

v48.1

  • [ORM] Attempting to upload Documents (files/images) with no filename will now throw an exception.
  • [WPF] Small tweaks across the UI: search screens return to page 1 when searching; collection sections now treat their expandedness correctly; Content screen titles update on EntityChanged; Selector text is lon longer centred; readonly dates now display as dd-MMM-yyyy instead of dd-MM-yyyy.
  • [WPF] Display will now raise EntityOpened only if the entity is not new (was loaded from the database). It will now also be raised when saving a Display screen if the entity was new before the save. This lets Display better serve its present dual role of Create.
  • [WPF] Collection fields have been refactored, fixing performance and correctness issues in LookupCollections. ValueCollection hasn't escaped; its actions are renamed to Create and Delete, which is what they (now) do - rows removed from the list will now result in actual deletion of entities if you go on to save.
  • [WPF] ImageControls have been enhanced. They have a context menu allowing for saving, external opening, and rotation (when editable). Progress indicators are displayed and file extensions are automatically calculated. The rotation-transformation functionality is also available in code on ImageProperty.Image. Finally, they now become temporarily invalid while an image is uploading.
  • [WPF] The new list editability heuristics are in. Lists can only be inline-editable if they have 3 or fewer fields; this behaviour can be altered for any given entity with a Models.EntityList replacement which overrides IsEditable. Small lists which are editable inline do not display a hyperlink for modal editing, and cannot have columns added or removed.
  • [WPF] EntityListRow overrides can now specify a background brush, calculated based on entity properties if they feel like it.

v48.0

  • [ORM] The semantics of IEntitySet have changed. SetChanged is guaranteed to be raised for additions to the set, but removals will not necessarily raise the event. This is in keeping with the inability to detect in-datastore deletions before save, and in general the whole class of problems requires user intervention to perform conflict resolution. In the meantime, this weakened guarantee enables significant performance improvements.
  • [ORM] New PreferenceStore implementation: 'appdata', which saves to a file in the user's AppData/Roaming directory. Preferences are flushed every minute or when manually invoked (which an app should do on exit).
  • [ORM] The.Pluraliser gained a new method, PluraliseLastWord(). It probably does what it says.
  • [SQL] Non-nullable attributes generated for a model without enforced nullability now have defaults set on their columns. This is to prevent spurious nulls from turning up during e.g. bulk data imports and making it hard to search (as these attributes cannot be treated as nullable in code).
  • [SQL] Ordering by attributes of null relationships no longer generates an inner join which eliminates all the results.
  • [SQL] Performance: GetAll() is now 'free'; it doesn't make any database calls initially, only stores the data necessary to reify the set at a later data.
  • [SQL] Performance: .Count on query result sets no longer requires a database call.
  • [WPF] Improved search screen error handling: errors applying search criteria are now trapped (instead of causing a crash). The search will continue with what criteria it can still apply, displaying a warning message about the one that failed. In order to reduce the number OF these errors, [Search] is now disabled when any fields are invalid; [Refresh] can still be used but will ignore invalid criterion fields.
  • [WPF] Content screen validation is now performed and displayed at the Section level as well as the Field level.
  • [WPF] Performance: Lookup factories now cache their lookup set for a given context.
  • [WPF] Bugfix: Readonly lookupreference fields are now readonly.

v47.0

  • [ORM] Added a user preferences infrastructure, configured by plugin key PreferenceStore. The first backend is "none", meaning that preferences exist in memory within a session but are not persistent. IPreferenceStore implementations are simple string key-value stores which support get, set and test operations.
  • [ORM] The plugin/IProvider system has been refactored to eliminate boilerplate and fail-fast. You may see exceptions at startup now if you'd failed to specify some appSettings - previously this would fail later at runtime, which sucked.
  • [ORM] IEntityInfo Parent has been moved from RelationshipInfo to its parent class, PropertyInfo - meaning that AttributeInfo now has a parent as well.
  • [WPF] The The.Preferences.PreferenceManager is now used to persist some UI configuration - textbox heights, screen expansion, the presence or absence of columns in lists. NotificationManager has been expanded to multiplex preference updates for immediate feedback across multiple screens. The .Expanded() and .Collapsed() combinators have been removed from ISectionModel, since its state is now user-controlled.
  • [WPF] Bugfix: there was an unclickable area of List headers, potentially large.

v46.0 - 20 Aug 2014

  • [ORM] Improved change description for relationships.

  • [SQL] QueryTranslator now does overload resolution, checking that the functions it's translating are the variants it actually supports. For example,

    previously .FirstOrDefault(Func<T,bool>) would translate to the same query as .FirstOrDefault(), ignoring the passed closure.

  • [WPF] Added two convenient ways to create field views: SimpleFieldBase, which can be used as a base class for code-defined views, and UserField, which can be used analogously to UserControl, implementing more custom fields. SimpleFields automatically manage all field behaviour, swapping between subclass-defined immutable and/or mutable element trees; UserFields allow custom management of editability and definition in XAML rather than code.

    Label+content fields, now that they're standardised, have been improved in a a number of ways:

    • making textboxes readonly is now built in instead of delegated to a required style
    • fields now have correctly constrained width; they'll scroll or wrap internally rather than growing out of sight
    • performance is improved - screens with a lot of fields layout faster The cost(?) of this is that fields require a width constraint; otherwise their content section will stretch to whatever contains them.
  • [WPF] Images in readonly lists are now displayed as an ImageControl directly instead of a full field. There's a new ListImage style for these controls.

  • [WPF] Setting MaxColumnWidth for ListGrid style has been tested and should work.

v45.0 - 19 Aug 2014

  • [ORM] DescribeChanges now returns an IReadOnlyDictionary mapping IEntities to their changes.
  • [WPF] Some generated sections now display subtitles - counts of elements in a collection.
  • [WPF] Bugfixes for add/remove column functionality related to the hyperlink column
  • [WPF] Bugfix: Image and Document FieldModels weren't always raising all the correct PropertyChanged events when content was uploaded/deleted.

v44.0

  • This release comes with an addin update.

  • [ORM] After cloning an entity, the attribute of the clone are calculated even if CalculationMode.Persistent. This addresses the common use case of reflecting changes made in modal screens.

  • [ORM] Autonums are now supported in calculated properties. The persistence engine predicts the value of the autonum, backing out of the

    transaction and repeating if it gets it wrong.

  • [ORM] Bugfix: DescribeChanges was missing some changed relationships.

  • [ORM] Bugfix: Repeatedly populating a collection with the same entity and then clearing it was failing with InvalidOperationException.

  • [WPF] ColumnPanel has been improved. It now enforces fixed widths in a way which lets its children auto-size, nest, etc by not themselves

    having fixed width; the equal-width columns are spaced across the screen with a configurable gutter between them. The column-height balancing algorithm has been rewritten and produces a much better result, particularly for the common two-column case.

  • [WPF] New .Expanded() and .Collapsed() combinators on ISectionModel.

  • [WPF] Relationship sections are named using their custom label rather than property name, if one exists. A title-cased section name is formed from the property name otherwise, in the same way as is done for field labels.

  • [WPF] EntitySelector improvements: better magnifying glass icon, button chrome restored, spare tabstop removed.

  • [WPF] FINALLY the datagrids in List screens no longer catch the mousewheel unnecessarily and you can scroll past them. They will still eat scroll events if they actually have a vertical scrollbar which isn't relevantly terminal.

  • [WPF] ImageField no longer purports to allow you to delete imaginary images.

  • [WPF] Create pseudoscreens now go into the local display cache, if not the actual pin list.

  • [WPF] Bugfix: field DisplayOrder now works once again.

  • [WPF] Bugfix: adding columns to lists now works once again.

  • [WPF] Bugfix: Opening a screen containing a File field would cause a hang.

v43.1

  • [WPF] Added ColumnPanel, which distributes sections (or other content) evenly across columns up to its horizontal

    width, growing downwards. Its balancing algorithm isn't very good yet! EntityDisplay's vertical (rather than horizontal) scrolling has been restored.

  • [WPF] Modal displays (lightboxes for editing e.g. collection members) now allow the OK button even when "unchanged"-

    from a user's point of view, it was not clear whether they were "changed".

v43.0.2

  • [WPF] Themes used within the Pager control are now DynamicResources rather than StaticResources

v43.0.1

  • [WPF] Bugfix: The Pager theme added in v43.0 was not included in the Theme Auditor

v43.0

  • [WPF] Pager is now themeable.
  • [WPF] Bugfix: Non-modal Create screens (which are actually Display screens) were not registered with the controller cache.

v42.1

  • [ORM] EntityBaseInfo attribute indices did not correspond to reality.
  • [WPF] Sections containing only non-visible content are no longer displayed.
  • [WPF] Added .WithName() combinator to give sections dynamic titles.
  • [WPF] Main section is named "Main Detail" by default.
  • [WPF] Content Screens with a single section 'collapse' into whatever it presents.
  • [WPF] Redesigned ValueReferenceField to work better with sections.
  • [WPF] ShowOnForm is now correctly respected within sections (it was generating invisible 0-size fieldcontrols).

v42.0.2

  • [ORM] Bugfix: EntityCollectionProperty would not raise its SetChanged event if it was changed via a Copy operation.

v42.0.1

  • [WPF] Added WithField combinator to ISectionModel - this is probably temporary.

v42.0.0

  • [WPF] Sections are now displayed using The.WPF.Controls.SectionControl, which works like FieldControl - give it a datacontext.

    This is the analogous ISectionModel; there's a convenience SectionModelBase and one existing implementation, FieldSection. Like IFieldModels, ISectionModels are immutable, modified by wrapping with combinators.

  • [WPF] Content screen overriding now uses classes rather than structs to define its overridden elements - GetCustomFields() &

    GetCustomSections() return IEnumerable<ContentFieldDefinition> & IEnumerable<ContentSectionDefinition> respectively.

  • [WPF] Content models are no longer used as the viewmodels of List rows. There's a new ListRow VM which can be separately overridden instead. This is to prevent the evolution of sections from interfering with lists, which don't use them.

  • [WPF] Bound value collection fields, when opening a modal add dialog, clone the existing screen data into it so that custom

    validation & lookups will have the context they expect.

v41.0.4

  • [WPF] Content sections are now displayed in vertical columns rather than horizontal rows.

v41.0.3

  • [WPF] ScreenField brokenness bugfix.

v41.0.2

  • [ADDIN] Class screen now indicates whether or not a property is displayed.
  • [WPF] Removed quasisection chrome from ScreenField.

v41.0.1

  • [WPF] DisplayOrder now affects the ordering of sections as well as the ordering of fields within a section.

v41.0.0

  • This release comes with an addin update.

  • [ADDIN] Attributes and relationships of entities now have a "display section" modelled. Along with the "display order" property, this is used by UI modules to generate or scaffold screens. Class Explorer now displays both attributes and navigable

    relationship-sides inline when editing entities, sorted by their section and order. Double-click will edit either, and legacy-only properties (which do not get displayed) are indicated by greyed-out text.

  • [ADDIN] Bugfixes - there were a few ways to try and add relationships or attributes which could crash if steps weren't performed in the expected order.

  • [ORM] Even stricter checking of calculation modes for Transient Calculated attributes- it basically only makes sense for them to be live-calculated, including their defaults, so an exception will now be thrown in any other case.

  • [ORM] Bugfix: Copying an entity could result in a copy with relationships with out-of-sync OriginalValues and CurrentValues.

  • [ORM] Removed some more codegen for LegacyOnly entities.

  • [WPF] Generated Content views have been removed, replaced by a generalised EntityContent view which uses the concept of screen

    sections. Sections are expandable, fixed-width units, each of which displays a set of modelled or custom fields. Section expansion replaces Load buttons as the mechanism for lazy-loading relationships. Content views can still be overridden but this should be less frequently necessary. The implicit API for overriding views has not changed, but the explicit inheritance API for overriding models has altered: GetCustomFields() is now required to return field name and section name along with actual IFieldModels. Consequently, custom fields are now completely on par with generated fields in terms of automation and validation. Custom sections can be added in overriding models by passing extra section titles to the constructor of the generated model class. The presentation of relationship fields has changed, and may change further: previously, each was displayed in a groupbox, the same UI paradigm that's now used for sections. At present, relationship/"subscreen" fields have no label UI at all, and are intended to be presented within a section which acts as the label.

  • [WPF] The Views template has been removed entirely.

  • [WPF] Screens opened from search results should now always get new contexts. This should fix some problems with refreshed screens keeping stale data.

  • [WPF] EntitySelector now exposes the SearchMode boolean property, allowing views to override whether it uses a dropdown or a search.

  • [WPF] Bugfix: Display screen controllers were being cached even after the screen was entirely closed, with undesirable consequences.

v40.1

  • [ORM] Bugfix: Entity.Copy(context) did not use the supplied context! This was causing problems for the ShoBiz "Describe Location" wizard.
  • [WPF] New single-selectors are now live, replacing the summary tile-based 'click selector'.

v40.0.2

  • [WPF] Bugfix: Selectors completely didn't work at all (internal preparatory refactoring gone mad).

v40.0.1

  • [WPF] Bugfix: Selecting Cancel in the modal screen opened when adding to a list did not produce the desired results.

v40.0

  • [ORM] RelationshipBase.IsPresent is now a property. EntityReferenceProperty gains an additional .HasValue property. Both of these can be safely evaluated without triggering lazy-loading.
  • [ORM] Special HOBS support removed from property metadata.
  • [ORM] More validation of calculated attribute config.
  • [ORM] Bugfix: transient calculated attributes with CalculationMode=Live and DefaultSource=Calculation with dependencies on noncalculated attributes could erroneously HasChanges=true after an entity was loaded from the database.
  • [WPF] Stricter separation of Display and DisplayModal functionality - Display screens now always save and load from the database by ID, never cloning. DisplayModal clones in and out of a context, never hitting the database directly. It's just proven too difficult to make correct use of the more flexible version in application code, and the performance benefits of cloning rather than re-loading something don't make up for that.
  • [WPF] Adding entities to collections now uses a modal dialog rather than edit-in-place.
  • [WPF] Filled in the 'missing' relationship fieldmodel factory overloads, via template.
  • [WPF] Bugfix: Restored the 'Search' button to selectors' modal dialog - these are slated for redesign, but in the interim, they need to at least function.
  • [WPF] Bugfix: Re-databinding EntitySelector would fail with a nullreference. Now it doesn't.
  • [WPF] Bugfix: Hyperlink columns might now stop vanishing from lists.

v39.0.5

  • [ORM] Bugfix: enum cache could fill with nulls if GetByID requests were made for objects under construction. In particular, the shobiz PinManager was causing this problem.
  • [ORM] Bugfix: copied entities were having their DataState copied from the source entity. This was resulting, in some situations, in copies that couldn't be saved.
  • [WPF] The new nullable-boolean field now has a readonly mode.
  • [WPF] Pager control now uses smart pagesize selection from the available optionsl
  • [WPF] Bugfix: race condition in List screens which could try and fill in their model through a null pointer.

v39.0

  • New package: The.Test.Mocks. This DLL contains basic implementations of some framework interfaces for use in tests.

  • [ORM] IEntitySet now has a Context property. Previously, sets were implicitly but neither consistently nor inspectably contextualised.

  • [ORM] Calculated properties now take a DefaultSource enum to configure their default source, rather than a boolean.

  • [SQL] A default query timeout can now be set with the QueryTimeout app setting.

  • [WPF] The M-V-C infrastructure has been simplified. IController is no longer generic, and screenmodel interfaces (like IEntityDisplay<T>) have been removed. Screens have been split into modal and modeless screens; typed (generic) modeless screens are also embeddable. Direct access to the model of a generated screen is now rarer and, when it takes place, invariant + concretely typed. Screens no longer modify their children unless directly embedding.

    The all-purpose Display screen has been split into Display, DisplayModal, Create and CreateModal (with the latter two being special cases for now). Search has been split into Search and SearchModal. This allows screens to avoid modifying and hooking their children, instead using IModalController<T>'s async interface to obtain and process a dialog box (lightbox) result.

  • [WPF] A simple event registry has been added for views of and modifications to entities. It's accessible at The.WPF.Composition.Root.NotificationManager

  • [WPF] As a result, of the above changes, screen deduplication is no longer error-prone- any remaining edge cases can be hunted down one by one now that the core system is sound.

  • [WPF] CommandRole.Close is now PopModal, which more accurately reflects its purpose - it is a command which can be invoked by the shell for the special purpose of closing a modal screen.

  • [WPF] Search screens have attained clarity of purpose. They no longer take an initialResultSet parameter which is potentially irreplicable by user-entered criteria. Further, the generated criteria factories no longer have built-in caching, making them reusable. This is leveraged to allow switching from advanced back to simple search mode.

  • [WPF] Nullable boolean fields now describe their null value as "null" rather than "any".

  • [WPF] The resizable multi-line textbox control has been further improved.

  • [WPF] Readonly fields will now have their text selected when gaining keyboard focus (this lets you tab through them and copy data).

  • [WPF] Performance improvements for lookupreference fields. (Non-editable ones no longer require a database call.)

  • [WPF] Performance improvements to the data templating system (affects startup).

v38.1

  • [ORM] Nullable String attributes now perform the same length checking as non-Nullable String attributes.
  • [ORM] Bugfix: Specialised attributes (i.e. images, files) weren't having their values copied when cloning
  • [WPF] Fixed incorrect spelling of "Initialise" in controller templates.
  • [WPF] The default search mode for text/string criteria has been changed from "starts with" to "contains".
  • [WPF] MultilineTextBox now uses a drag-to-resize approach, rather than an embedded button.
  • [WPF] TriStateChoice now has customisable text, making it look a little less out of place on search screens.
  • [WPF] New list columns are now added at the point where the user clicked, rather than at the end of the row.
  • [WPF] AutoCompleteComboBox now has nicer Enter key behaviour (see THE-450).
  • [WPF] Bugfix: Required validation attribute now works correctly for nullable primitives (though I don't know why you'd want to do this).
  • [WPF] Bugfix: validation rules were not running on brand-new entities added to lists unless those entities had been changed.
  • [WPF] Bugfix: ImageFields' ImageControls weren't always updating when the FieldModels behind them were changed.
  • [WPF] Bugfix: readonly lookup relationship selectors were unnecessarily loading the list of available choices.
  • [WPF] Bugfix: making fields .Immutable() did not work in lists.

v38.0.1 - 26 Jun 2014

  • [WPF] Bugfix: ValueReference fields' Delete button did not work correctly, setting up a state which would produce an SQL error.
  • [WPF] Bugfix: HasChanges for relationship properties was using SequenceEqual to do comparisons, producing failures randomly.

v38.0 - 25 Jun 2014

  • This release comes with an addin update.

  • [ADDIN] Incredibly large performance improvements to every part of Class Explorer.

  • [ADDIN] Fixed venerable bug THE-78, where adding a relationship to a brand new entity would crash Class Explorer.

  • [ADDIN] Fixed a similar but separate crash bug, triggered by adding a relationship targetting an entity which was not expanded in the treeview and then clicking on the "Loading..." node which was left behind.

  • [MODEL] Removed the 'simple description column' property from Entities; it was not implemented, and this role is now served by

    the Text calculated property.

  • [MODEL] Replaced unimplemented "default ORDER BY" property with "default sort attribute" and "default sort direction" properties, templated to produce an abstract default ordering in generated IEntityInfos.

  • [ORM] Calculated property semantics have changed, offering a choice between immediate consistency and consistent performance.

    Here's the short version: they're calculated on save, unless you haven't saved yet. Implementations GetFoo() must now be marked with the <Calculated> attribute from The.Attributes; this attribute can be inherited from base class implementations (as in GetText()), and takes two arguments. The first is a calculation mode. In CalculationMode.Live: * the originalvalue of a calculated property will be set at entity creation time or from the datastore * currentvalue will always be calculated on demand and during save In CalculationMode.Persistent: * properties for entities in State.Creating will be in 'live mode', updated when accessed; then, * once saved or loaded (State.Loaded), persistent properties will have the currentvalue that was last saved or loaded; however, * during save, the property values will always be recalculated So which one do you use? Persistent properties use the datastore as a cache, avoiding expensive recalculations except during (rare) saves. The property value will only be fully consistent with its definition when it is represented in the data store. Often this is not a problem in practice. Live properties are for the case when immediate consistency is required. They don't make good fields or list columns, unless their calculation is trivial. The default for the Text property is Persistent, for this reason - it frequently requires an expensive calculation, and it's used all over the place. The question of how calculated properties should relate to HasChanges is still open. Right now, they can only be HasChanges=true when Live, or in the temporary live mode of a newly created entity. This mode itself is a compromise for convenience, allowing persistent properties that do not yet have a cached value to still present a value, even if they have to calculate it on the spot. The second argument to CalculatedAttribute specifies whether to use a calculated originalvalue on initial creation, ignoring the defaultvalue specified in the model. This is true for EntityBase.Text, but might be an inappropriate choice for user-defined calculated properties, since it forces them to be evaluated immediately. Use it if no reasonable static default value can be entered, but a reasonable default can be calculated from the defaults of other attributes.

  • [ORM] Calling .Equals() on a specification when you meant .EqualTo() is a common source of bugs. This will now throw an exception instead of silently failing to do anything.

  • [ORM] IEntityInfo is now immutable; property DefaultCaption has been replaced with readonly property Caption.

  • [WPF] List and Search screens support the new default sort model properties - if the user hasn't selected an ordering, they'll be ordered by whatever was set in the model, falling back to modifiedOn Ascending if nothing is set.

  • [WPF] Added a "ScreenField" (FieldModelFactory.CreateScreen) which can be used to present screens as fields, with label and

    validation and so on. This is kind of the framework equivalent of ContentControl, which presents a view as a control.

  • [WPF] Invalidate() moved from IFieldModel<T> to IFieldModel. It's not useful on fieldmodels without a T, but you might want to call it without knowing what that T actually is.

  • [WPF] A limited form of support has been added for custom fields hooking into contentmodels' validation system. Content model subclasses can now override GetCustomFields and return a sequence of IFieldModels, which will propagate HasChanges and

    IsValid to the screen like generated fields do. They will not gain automatic lazy creation or automatic RaisePropertyChanged.

  • [WPF] New style for subscreen elements of fields, which allows applying common background colors, borders, error template, etc.

    In particular, this means that reference and collection fields now respect The.WPF.Themes.Keys.ErrorTemplate, as does the new ScreenField.

  • [WPF] Image fields now update immediately when a new image is uploaded.

v37.1.2 - 25 Jun 2014

  • [ORM] Fix endless recursion causing a StackOverflowException in DynamicEntity.GetText.

v37.1.1 - 20 Jun 2014

  • [ORM] Fix up the process of calculating properties during save so that it doesn't cause CollectionModifiedExceptions or fail to calculate some data.

v37.1 - 20 Jun 2014

  • [ORM] Optimised EntityContext.Save()
  • [ORM] Added EntityContext.RemoveAll()

v37.0 - 20 Jun 2014

  • [ORM] Added Text calculated property to EntityBase, which is now used for ToString() and can be searched.

  • [ORM] IEntitySet.GetPage orderings can now order by relationships as well as attributes.

  • [ORM] EntityBase supplies a working value equality implementation for entities, which can no longer manually override GetHashCode and Equals.

  • [WPF] List screens now allow sort by an entity's description/hyperlink field, which displays its .Text, as well as by relationship columns

    (these also sort textually). Binding errors on these screens have consequently been fixed. The 'add column' dialog has also been improved.

  • [WPF] Search screens now allow resetting criteria and exiting Advanced mode. Their generated CriteriaFactories are now more customisable.

  • [WPF] Display screenmodel base now exposes its Content subscreen to subclasses WithEvents.

  • [WPF] Image fields now support uploading new images.

  • [WPF] Multiline text fields now display as a single line with an expander control, using The.WPF.Controls.MultilineTextBox

  • [WPF] AutocompleteTextBox now does the equivalent of a Contains search, not just StartsWith

v36.1.1 - 17 Jun 2014

  • [WPF] Bugfix: attempting to sort by lookup fields STILL crashed lists, if they were non-editable lists.

v36.1 - 16 Jun 2014

  • [ORM] RelationshipInfo now has a public constructor.
  • [ORM] Relationship performance improvements. (THE-384)
  • [ORM] Bugfix: relationship remote-update did not work on collections which had not been previously accessed (THE-409).
  • [WPF] New tri-state field available for nullable booleans.
  • [WPF] ImageControl no longer has a hardcoded tooltip.
  • [WPF] Bugfix: attempting to sort by lookup fields would crash lists. (THE-388, THE-410)
  • [WPF] Bugfix: lookupcollections did not correctly enable/disable their Remove button (THE-402).

v36.0.1 - 12 Jun 2014

  • [ORM] Bugfix: collections were loaded too often.

v36.0 - 12 Jun 2014

  • [FORMS] For now, the WinForms UI library is unsupported. The common base ORM has diverged sufficiently that

    it is no longer maintainable without some time allocated specifically to the task.

  • [ORM] The DataState class, which tracks the datastore sync status of entity and relationship kernels, has been formalised as a state machine. There is no more public access to its actual enumerated

    state value, only to transitions and properties.

  • [ORM] Relationship internals have been completely rewritten- mostly a simplification. There should be

    no observable changes in the generated API apart from bugfixes - cloning or updating complex object graphs should be faster and more reliable. However, code which has been using .Props to access EntityCollection or EntityReference types may need updates. ReferenceSide no longer exists.

  • [ORM] Attributes and Relationships have been disconnected; PropertyBase has been removed. Both types

    still share an interface, IHasChanges, but no common hierarchy.

  • [ORM] A number of types have been made immutable, including EntityKernel and the new ReferenceKernel.

    Corresponding readonly properties have been made readonly fields.

  • [ORM] Removed the old NotifyPossibleChange system - there's been a ValueChanged event on attributes for

    a while which can be used instead.

  • [ORM] Removed the ill-conceived EntityKernel.DiscardChanges. IHasChanges implementations (attributes, relationships, entities) have MarkUnchanged instead.

  • [WPF] Bugfix: Multiline text fields no longer demand a tooltip.

  • [WPF] Bugfix: FieldModelFactory.CreateLookupCollection() would fail if not passed an allegedly optional parameter.

  • [WPF] Bugfix: Default SharedSizeGroups were wrong for fields based on the new xaml-less controls.

  • [WPF] Bugfix: clicking on the first header in a grid would crash it.

v35.3 - 11 Jun 2014

  • [WPF] EntitySearch controller's GetResults method is now public; this returns the set that would be used if the user clicked search with the current criteria.

v35.2 - 10 Jun 2014

  • [DOCUMENTS] Obsoleted the Upload function that required file metadata when uploading by filename. Added an

    Upload function that doesn't require this metadata.

  • [WPF] Added an ImageControl and an ImageFieldModel/View. ImageFields can be styled using the a style with the ImageField key.

v35.1.1 - 29 May 2014

  • [WPF] Optimised display of non-editable List screens; rather than fully databound [immutable] fields,

    they just present tabular text. It's now feasible to display dozens of columns on a search result screen if we want to, and functionality like export-to-CSV would be easy to build on top of this.

  • [WPF] Screens presented by the framework are now fixed-size; if necessary they will contain internal

    scrollbars around variable-size content regions. They should not be presented in an external ScrollViewer. Views for custom IScreenModel implementations should also be fixed-size - I recommend using e.g. DockPanel instead of Grid for top level containers.

  • [WPF] Enabled by the above, lists now virtualise their contents.

  • [WPF] Bugfix: List pager was showing up erroneously.

v35.1 - 28 May 2014

  • [ORM] Added a cache subsystem to persistence. The CachePolicy appSetting controls which cache plugin is used; at the moment the framework provides one useful policy, "enum". With this cachePolicy, all

    enums (reference data) will be cached in memory on first load and will be reused for the lifetime of the application.

  • [ORM] Entities now come preloaded with their references' IDs, rather than just 0 or 1. This means that

    if the referred entity is already in the context- for example, when hooking up the other side of an enum- no database calls are necessary.

  • [ORM] Calculated properties are no longer calculated at entity construction time. No cost is incurred for the property until they are actually accessed or the entity is saved.

  • [WPF] Added a dropdown->picker threshhold even for reference data (set at 200 for now).

v35.0.1 - 28 May 2014

  • [WPF] Restore tabularity overridability.

v35.0 - 28 May 2014

  • [ORM] EntityKernel now stores its properties in arrays, rather than dictionaries. Templates generate

    array index operations instead of lookup by name, leading to faster code in a number of places.

  • [SEARCH] .Contains()/.Any() queries now support more types of collections.

  • [WPF] Removed more XAML.

  • [WPF] New control: The.WPF.Controls.FastTabControl. It's like TabControl, but fast.

  • [WPF] FastObservableCollection was insufficiently fast and excessively observable. Added a complementary

    SlightlyObservableCollection in The.WPF.Utility.

  • [WPF] Improved performance when creating Content models with a lot of fields.

  • [WPF] Lists are now ordered by modifiedOn by default.

  • [WPF] Bugfix: drag-dropping columns to the very beginning or end of lists could cause problems.

  • [WPF] Bugfix: when a list contained no field columns, its title column was not displayed.

v34.0 - 23 May 2014

  • [WPF] Fix bugs in the fixed-width grid layout and generally smooth out its rough edges - no API changes but it should look and feel better.

  • [WPF] Prefetch list pages optimistically, so that the next page begins loading before it's requested.

  • [WPF] Theme updates: "screen" highlight brushes have been more-accurately renamed FieldXXX, and a

    ScreenOverlay brush has been added (this is used when a screen is 'greyed out' by loading).

  • [WPF] Common field views rewritten without XAML - a major performance gain with a small maintainability price.

v33.3.1 - 23 May 2014

  • [WPF] Experiment with an alternative grid layout.
  • [WPF] Bugfix: grid sorting was broken.

v33.3 - 23 May 2014

  • [WPF] Performance: improvements to field display, content layout, list layout, list loading and cloning.

v33.2.1 - 22 May 2014

  • [WPF] EntityLink controls now correctly become disabled if their containing view is IsEnabled=false.

v33.2 - 21 May 2014

  • This release comes with an addin update.

  • [ADDIN] Bugfix: "Suppress in Search" was mislabelled for columns.

  • [ORM] Bugfix: cloning an entity could mess with the states of its relationships in subtle ways, leading to later failures. This manifested mostly as save failures on screens opened from index pages.

  • [ORM] Bugfix: cloning an entity could also, in extremely obscure circumstances, cause its collections to be

    reordered, which should not matter for set-based equality, but did. Now it doesn't.

  • [ORM] Bugfix: Non-navigable relationships were not always updated if set from the other, navigable side. This could cause multiple problems on save, both errors and loss of data.

  • [WPF] Improved validation performance - rules that are known to have no cross-field dependencies will not be

    triggered on screen text changes. Evaluating everything on every keypress was slowing down forms.

  • [WPF] New field combinator: .Relabelled()

  • [WPF] The "Save" command on Display screens is no longer role [Close] - it's now [Confirm] role, and when these screens are displayed modally an extra "Cancel" command is added with [Close].

  • [WPF] Generated Date & DateTime criteria are now a range of two dates. The TwoDates field is also available

    in the fieldmodel factory if you want it for some other purpose.

  • [WPF] Bugfix: hidden summary form of List could activate when Enter was pressed, with mysterious results.

v33.1 - 21 May 2014

  • [WPF] Added some margins to search criteria.
  • [WPF] New theme Brush - Keys.ScreenSelectionInactive. You can use this instead of overriding DataGrid.RowStyle.
  • [WPF] New logging setting, LogValidation. This will log field/screen invalidations to help debug cascades.
  • [WPF] Dropdowns are always used (instead of selectors) for reference data.

v33.0.1 - 20 May 2014

  • [WPF] Bugfix: changes to lookupreference fields were not raising IsValid.

v33.0 - 19 May 2014

  • This release comes with an addin update.

  • [ORM] Potential bugfix for a HasChanges issue that occurred only after cloning, where the ReferenceSides of a relationship could be recreated multiple times such that a collection's OriginalValue was

    value-equal but not reference-equal to its current Value.

  • [WPF] Removed the two subclasses of 'Collection' screens. There are now only List screens - which are

    by default tabular data, the mode which used to be called Grid . This is a temporary measure to go-live and elicit client feedback; there may still be a need for summary tiles, but we need a proper design, and the more important concern for now is to increase data density. Lists can now be sorted and columns can be reordered, added or removed. The sorting is backed by IEntitySet and should be stable for a given set of sorting criteria. The available columns are the fields defined in an entity's Content screen (by default, the ones that are not marked SuppressInList, but users can add all of them back if they like). Summary lists are still possible, enabled by a new EntitySummary control - this can be used standalone, to display the summary for its bound entity or a special 'missing' summary. To create a summary list override an entity's List model to be non-Tabular or pass tabular:=False to FooList.Create(). At the moment, EntitySummary has similar restrictions to EntitySelector: they need a Screen, and must be bound to a concretely typed SomeEntity (rather than IEntity).

  • [WPF] New ListHeader style for grid column headers. It's necessary to use this style instead of setting

    the grid's ColumnHeaderStyle (e.g. in ListGrid), or the List screen will not pick it up.

  • [WPF] SuppressInTree has been removed and replaced with the more useful SuppressInSearch. Columns marked SuppressInSearch will not be displayed as search criteria on generated search screens,

    unless the user adds that criterion back (currently, the way to do this is to add them all at once by selecting Advanced search mode).

  • [WPF] Search criteria wrap into columns. Boolean fields now respect ContentSizeGroup, which without this wrapping looked terrible.

  • [WPF] Fields which are both SuppressOnForm and SuppressOnList do not contribute, by default, to Content screen validity/changedness. If those fields are overridden or explicitly accessed then they will

    be counted for IsValid and HasChanges from that point.

  • [WPF] Double-clicking or hyperlink-clicking an entity in a selector's Search popup will now select that entity instead of opening it in a new screen.

  • [WPF] Bugfix: FieldControl.ContentSizeGroup was not correctly overridable by views. It was continuing to use the value provided by the viewmodel, not the one supplied in XAML.

v32.2.1 - 15 May 2014

  • [WPF] Bugfix: FreeAttributeModel.HasChanges

v32.2 - 15 May 2014

  • [WPF] New fieldmodel factory methods for lookup and value references which allow them to be created without a specific property's metadata.

v32.1.1 - 15 May 2014

  • [WPF] Bugfix: too stupid a bug to mention

v32.1 - 15 May 2014

  • [WPF] ICriteriaFactories are now supplied with an IScreen when generating their criteria.
  • [WPF] Bugfix: picking null from search popups would crash.

v32.0.2 - 15 May 2014

  • [WPF] Bugfix: Invalidate()'s dispatcher usage was incorrect.

v32.0.1 - 15 May 2014

  • [WPF] Search screen result areas now grow to fill available space.

v32.0 - 14 May 2014

  • [ORM] IEntitySet is now a subinterface of IReadonlyCollection. This allows the use of IReadonlyCollection<IEntity>, a covariant supertype of all IReadonlyEntitySet<T>, to call the Count property in less-typed code.

  • [ORM] SetOriginalValueToCurrentValue is now public on attributes. This may go away again - it's been enabled for the narrow purpose of allowing a transient property's changedness to be reset. Ideally that would be solved

    in a more targetted fashion.

  • [SEARCH] Bugfix: StartsWith and EndsWith criteria would fail if passed null.

  • [WPF] New Search screens are available. These screens are used by entity selector controls (as part of reference/collection fields) and can also be used as a kind of top-level index to some entity's

    functionality. They perform searches based on a set of criteria dispensed by an ICriteriaFactory<T,U> where T is an entity and U is a specification type for that entity. Basic criteria factories are generated as [modelnamespace].Controllers.[entity]Criteria; these can be overridden or reimplemented to customise the criteria selection. The base implementations contain a criterion for each ShowOnForm attribute, which can be dispensed by subclasses if desired.

  • [WPF] Added The.WPF.Controls.EntitySelector, a control for picking entities from a set. It must be bound to an IScreen, a T and an IReadonlyEntitySet<T>, and will then display either a drop down combobox

    or a search screen based picker.

  • [WPF] Added The.WPF.Models.MissingEntityModel/View pair for displaying 'empty' summaries.

  • [WPF] Added The.WPF.Utility.EnumToBoolean converter and static resource; this converter returns True if the

    enumeration value has the flag indicated in its ConverterParameter. Sample usage: IsDefault="{Binding Roles,Converter={StaticResource EnumToBooleanConverter},ConverterParameter={x:Static models:CommandRole.Confirm}}"

  • [WPF] Improved default Summary view; made it easier to just override Summary model and get a tile UI.

  • [WPF] FieldModelBase now takes care of Label for you.

  • [WPF] IScreenCommand.Command now raises CanExecuteChanged at appropriate points.

  • [WPF] Changed Display hook names WillSave and DidSave to Saving and Saved.

  • [WPF] New theme keys for summary tile width and height (doubles).

v31.0.6 - 14 May 2014

  • [ORM] Bugfix: Calling EntityContext.Save on a context that contained entities with calculated nontransient properties that referred to other entities that were unloaded at the time of saving could cause an

    InvalidOperationException.

v31.0.5 - 09 May 2014

  • [ORM] Improve LogPersistence.

v31.0.4 - 09 May 2014

  • [ORM] Calculated transient properties only have changes if their calculated value has changed since the

    entity was loaded/created.

v31.0.3 - 09 May 2014

  • [ORM] The.ChangeTracking.DescribeChanges now correctly returns changes - it was broken and nobody noticed.

  • [ORM] VB.NET query syntax "Like" operator now works in queries

  • [WPF] Bugfix: Display screen save buttons were enabled for editable screens at all times once the screen

    finished loading.

v31.0.2 - 08 May 2014

  • [WPF] Bugfix: Value collections were being displayed with lookup collection fields when not in a subscreen.

v31.0.1 - 08 May 2014

  • [SQL] Bugfix: Attempting to save an entity that had changes to only its transient attributes would cause invalid

    SQL to be generated.

v31.0 - 07 May 2014

  • [FORMS] Moved GraphicBasics here from core.

  • [ORM] Changing entity relationships now makes the correct 'remote' changes to maintain 1:1 and 1:m constraints.

    See THE-93 for details, but the gist of it is that if a reference = x and you set another reference equal to x, the first should become null, along with the equivalent guarantee for collections. More formally: A.X ≠ B <- C.Y = B A.X ∌ B <- C.Y ∋ B

  • [ORM] Removed the ForceChanged method added in 30.1 in favour of a different approach. The motivating factor

    for that change was to ensure that newly added calculated properties caused an entity to HasChanges(); change tracking for calculated properties has been improved instead. Like other properties, they have an internal "original value", which is now the default as set in the property or retrieved from the data store, and they will HasChanges() if their current value differs from this.

  • [ORM] Transient properties, too, now contribute to change tracking.

  • [ORM] It is now possible to clone entities of abstract base type T - the clone will be returned as a T but will

    have the same "real" type as your original entity did.

  • [ORM] Bugfix: LogPersistence was broken.

  • [ORM] Bugfix: Adding items to a collection without actually accessing any members of the collection could

    behave oddly, failing to detect that the items were already present. This affected ThesaurusWords.

  • [WPF] Instead of built-in 'command' buttons, screens now have an IScreenCommand collection which can be displayed by

    the application in whichever manner it chooses. Commands have a name, an ICommand and 'roles' which can be used by the shell to present special UI for their activation, as well as an IsEnabled toggle for the use of controllers. IScreenCommands can be created with The.WPF.Models.ScreenCommandFactory from either synchronous or asynchronous operations. The IsEnabled toggle is is particularly relevant to async commands; although they will automatically disable themselves to prevent reentrancy, if a command executes asynchronously it may have to enable and disable other parts of the screen at appropriate times. Please try to implement UI actions as screen commands whenever possible. They provide automatic exception handling and will later be able to participate in user security/role features.

  • [WPF] There is now a general factory method for Display screens which allows installing load/save handlers, and simpler

    ones which display an entity in the database, or a clone, or a newly created entity. Display models now also have OnWillSave and OnDidSave hooks, which can be overridden to perform extra actions before or after the model is saved.

  • [WPF] Hooks now come with associated events, like in WPF - so there's an IEntityContent<T>.EntityChanged event, an

    IEntityDisplay<T>.WillSave event, etc.

  • [WPF] List screen factory methods now have an optional parameter for the initial page size.

  • [WPF] Validity now 'propagates' through Content and List screens such that the whole screen's validity depends on its fields' validity.

    Value reference and value collection fields have a new default validation rule requiring their sub-screens to be valid.

  • [WPF] Moved IScreen out of IShell - it's no longer an unimportant 'token' type but a first class abstraction in its own right.

  • [WPF] Bugfix: fields with Required set would generate some incorrect validation code if they also had a custom Caption.

  • [WPF] Bugfix: Display controller caching was a little overeager - lightboxes opened from lists were being reused.

    This may not be a comprehensive solution, but that specific case at least should be fixed.

v30.1

  • [ORM] Attributes have a new ForceChanged method that is hidden from IntelliSense. Calling ForceChanged causes the attribute to always return True from HasChanges until its parent entity is saved.

v30.0.2 - 29 Apr 2014

  • [ORM] Non-Nullable String calculated properties will now save the programmer from nulls should they explicitly code one by mistake,

    by transforming it to an empty string.

  • [SQL] OrderBy both an attribute of the entity and an attribute of a relationship simultaneously is now supported.

  • [WPF] HasChanges on fields not bound to entity properties was backwards, returning true iff there were no changes.

v30.0.1 - 28 Apr 2014

  • [WPF] Display screens no longer interrupt their own asynchronous loading to check save button validity.

v30.0 - 24 Apr 2014

  • [ORM] Cloning was still broken - the last bugfix-refactor introduced a new issue where 'copying back'

    data to a list by using Clone did not function. Its unit test coverage is now considerably higher and we're down to 0 known issues, for now.

  • [ORM] IEntitySet.Add and .Remove no longer return anything. This should make it easier to create

    implementations which do things like defer addition via a modal dialog.

  • [SQL] Bugfix: some persistence code was still being generated for LegacyOnly relationships.

  • [SQL] Bugfix: query generation would produce bad SQL if OrderBy() was used after a Where() function

    which translated to a left outer join. This affected inHerit search.

  • [WPF] Asynchronous list display has been improved. The UI should remain responsive at all times, with the work of loading data and creating viewmodels taking place on background threads, as long as

    summary views perform appropriate eager-loading.

  • [WPF] Field factory methods now include an optional initial value for unbound fields. There is no longer

    a field type for Version properties - this work revealed how different they are to other attributes.

  • [WPF] Comboboxes are sorted.

  • [WPF] Bugfix: save notifications were appearing on search screens.

v29.6.2 - 23 Apr 2014

  • [WPF] Bugfix: The Invalidate() change in 29.6.1 was incorrect.
  • [WPF] Added some documentation to IFieldModel.

v29.6.1 - 17 Apr 2014

  • [WPF] Bugfix: BLOB fields were invalid by default.
  • [WPF] Bugfix: Attribute fields did not always raise PropertyChanged(IsValid) when invalidated.

v29.6 - 16 Apr 2014

  • This release comes with a new addin version.
  • [MODEL] Added LegacyOnly flag to relationships, as well as adding an actual implementation of it for entities.
  • [ORM] Specifications no longer pretend that you can search by transient attributes.
  • [WPF] New lookup collection field UI.
  • [WPF] Mutable fields are now mutable.
  • [WPF] Increased default page size.

v29.5.1 - 14 Apr 2014

  • [ORM] Bugfix: Clones could have their collection contents multiplied.
  • [ORM] Bugfix: Clones could have their HasChanges reset to false.

v29.5 - 14 Apr 2014

  • [WPF] Generated Content models have a new overridable method OnEntityChanged(). This is a good place to put initialisation for entity-specific custom screen content.

v29.4 - 14 Apr 2014

  • [WPF] If used from within an EntityList, EntityLink controls will use the list's Open action.
  • [WPF] Bugfix: DelegateCommand<T> constructor was failing.

v29.3 - 11 Apr 2014

  • [ORM] The Text property already present on generated entities is now exposed through IEntity.
  • [ORM] Bugfix: Cloning had issues with cycles and collections.
  • [SQL] Bugfix: String.Contains did not work through references.
  • [WPF] New utility converter for hiding grid headers.
  • [WPF] Fieldmodel factory methods for references are now slightly more convenient.
  • [WPF] DelegateCommand can now subscribe to events in order to raise CanExecuteChanged.
  • [WPF] More of The.WPF is now covered by automated tests.
  • [WPF] Bugfix: Generated validation messages for IsRequired now use caption, not name.

v29.2.1 - 07 Apr 2014

  • [ORM] Bugfix: Cloning was not threadsafe if the same object was being cloned on multiple threads.

v29.2 - 05 Apr 2014

  • [WPF] Bugfix: BitmapImage creation leads to memory leaks.

v29.1 - 04 Apr 2014

  • Simplified Heracles theme.
  • Summary controller can now tolerate null entities as long as its model is ok with them.
  • Bugfix: Display screen was loading entities twice.
  • Bugfix: Pager control did not preserve state across rebinds.

v29.0 - 02 Apr 2014

  • [ORM] Finally renamed IEntityInfo.BaseName to IEntityInfo.Name. The implementing properties on

    generated metadata classes are called EntityName to avoid clashes with concrete properties named Name.

  • [SQL] Bugfix: QueryExtensions.Like() was failing when one of its operands was a relationship.

  • [WPF] All entity-specific screens can be now overridden even when there is no actual generated

    content; that is Content, Summary, Display, Grid and List. At the moment Display, Grid and List are open generics, but either the views or the models (or both) can still be replaced on a per-entity basis. The list of available screens is likely to change soon: Summary and Grid may be rolled into Content and List, and some candidates for addition include "Index", "Criteria" and "Create" screens. All of these will be overridable-per-entity if they eventuate.

  • [WPF] FooSummary views are no longer generated (but see above). There is a default EntitySummary.

  • [WPF] Added some nongeneric base types to viewmodels for the use of dynamic code like shobiz's

    pin manager.

  • [WPF] Templates simplified into Models, Views and Controllers - one for each generated namespace.

  • [WPF] Bugfix: Notifications could be displayed on the wrong screen.

v28.2 - 02 Apr 2014

  • [SQL] The generated CreateIndexes.sql script will now recreate existing foreign keys (using WITH

    NOCHECK) as well as creating missing ones.

v28.1 - 01 Apr 2014

  • [ORM] Bugfix: calculated properties were not able to see the correct state of an object during clone.
  • [SQL] Bugfix: queries which generated OUTER JOINs could produce duplicate results when iterated.
  • [SQL] Bugfix: queries which performed INNER JOINs within OR clauses could omit some results.
  • [WPF] Screen factory method convenience overloads added to IScreenFactory.
  • [WPF] Display screen loading no longer blocks the UI thread while calculating entity description.

v28.0 - 30 Mar 2014

  • [WPF] Display screens, like List/Grid screens, now load their content asynchronously, although they still require an id upfront for deduplication. The rationale here is that if you're opening some

    entity, you're about to either retrieve or clone it, and should have an ID available in both cases. The benefits of this asynchronous loading are twofold: DoRefresh now works properly on these screens no matter whether they were loaded from the DB, a list, etc, and a progress bar can be shown while data is retrieved and the inner Content screen is created.

  • [WPF] The asynchronous screens now have some convenience constructors. Rather than supplying a Func<T>

    directly, you can provide a Query or Specification in the case of List/Grid, and an ID or nothing (meaning: new entity) in the case of Display.

  • [WPF] Many cleanups around the Display and Content screens - Content no longer has any commands;

    Display correctly sets commands to null if inapplicable; creating Content-containing fields is simpler.

  • [WPF] Continued to merge lists and grids - Models.IPaging removed; grids no longer require any special

    ICommands on their models; one more generic parameter removed.

  • [WPF] Bugfix: lookups currently set to null did not load properly.

v27.1 - 29 Mar 2014

  • [SQL] EnableIdentityColumns.SQL will now fill in NULLs in the temporary __Foo_NoIdentity column before transforming it into the IDENTITY Foo column. This supports cases where a column has been used as

    non-IDENTITY for some time and is changed to become IDENTITY.

v27.0 - 28 Mar 2014

  • [ADDIN] New version 27.0.0 available from \acdc\AgileTools\CodeGenAddin, with some constraints and defaults to help model columns.

  • [WPF] Content screen overriding has changed. Instead of overriding properties that return fieldmodels

    (public readonly Foo), you now override functions that create them (public CreateFoo()). These will be used internally by the screen to hook up change events etc, and will be re-invoked if the underlying entity changes. There's no need to do any caching or event-handling in the overrides themselves.

  • [WPF] New EntityLink control - with Entity property bound, this displays a hyperlinked description. The

    OpenForEdit property can be used to control how it opens, and FallbackText is what will be displayed if it is bound to a null.

  • [WPF] Lookups currently set to a 'legacy' value will include that value in their dropdown list of options.

  • [WPF] More keyboard shortcuts.

v26.2 - 27 Mar 2014

  • [ORM] Bugfix: cloning something was setting active.OriginalValue to false, leading HasChanges to be true.

  • [ORM] Bugfix: attribute HasChanges was incorrect for BLOB and Version properties.

  • [ORM] Bugfix: relationship HasChanges was incorrect when the 1 side of a 1:m was nulled then re-set to its original value.

  • [WPF] Framework lookup comboboxes have been improved. They now support textual autocomplete and nicer keyboardability. These features have been split out of the LookupReferenceField view into two

    reusable controls: AutocompleteTextBox and AutocompleteComboBox. The.WPF.Controls.AutocompleteTextBox works like an ordinary TextBox with an ItemsSource property; bound to an enumerable of strings, it will enforce the entry of one of those strings as its Text property. The.WPF.Controls.AutocompleteComboBox adds the dropdown list, selection, etc, and if it IsEditable then it will contain an AutocompleteTextBox and switch focus as necessary between the textbox and dropdown. There is a new FieldCombo style in the theme for styling the ones in lookup fields.

  • [WPF] Now you can use Enter to open things from a list.

  • [WPF] Bugfix: save button enablement had come disconnected from validation.

v26.1 - 27 Mar 2014

  • [SQL] To support migration of SQL IDENTITY columns, the CreateTables.SQL template has been replaced

    with CreateTablesWithoutIdentityColumns.SQL and EnableIdentityColumns.SQL. A typical import operation would work like this:

    • Run CreateTablesWithoutIdentityColumns.SQL; this will create a column named __Foo_NoIdentity for each SQL IDENTITY attribute Foo.
    • Import data into entity tables, taking care to import into the temporary __Foo_NoIdentity column instead of Foo.
    • Run EnableIdentityColumns; this will create the SQL IDENTITY columns with values populated from the corresponding __Foo_NoIdentity columns.

v26.0 - 24 Mar 2014

  • [MODEL] Removed 'Overridable' storage flag - it is redundant with Calculated.

  • [MODEL] Storage flags in the class explorer gui now enable/disable each other as necessary to create a valid combination of settings. Everything you need to know is explained in the Mutual Exclusion Hexagon:

                                           Nullable
                                         /|          
                                        /            
                                      |/              
    
                                  Identity<------------>Calculated
    
                                      ^                ^
                                      |                |
                                      v                v
    
                                 Transient<------------>Legacy
    
                                      |\              
                                        \            
                                         \|          
                                           Audited
    
  • [ORM] Calculated properties are now fully supported, from db to gui. If you flag an attribute Foo as

    calculated, there are two effects: it becomes readonly, and an abstract method GetFoo is added to its generated classes. At some point we could add a separate 'readonly' flag to attributes and 'SetFoo' for read-write calculated properties. The Get___() method will be invoked whenever the value of the attribute is read, including during saves and other internal operations. Change tracking and other property functions will work as normal.

  • [ORM] EntityContext.HasChanges() is now a function rather than a property. It's slower but more accurate.

  • [ORM] Entity properties are no longer Overridable and nor are EntityBase methods - this is the apotheosis

    of frankenstein kernelisation. Members intended for override classes (GetText, calculated properties, etc) are now MustOverride instead. Other members should not be overridden or the kernel system would not be able to connect them up in the increasingly complex combinations required.

  • [WPF] Entity lists/grids now take an extra parameter: whether to open items modally or modelessly. This

    is intended to replace most custom DoOpen overrides that people have been using. While those overrides provide flexibility, they were causing some bugs and inconsistent behaviour. The choice of modality also controls save/close behaviour. If list elements are opened modally, their save command will not perform an immediate database save, but only copy changes back to the list context (the changes will still be copied for a modeless save, but an actual save will also occur).

  • [WPF] Screens can now be re-displayed or switched to. IScreen has a new method, Activate; this can be a hard

    switch, an attention signal, whatever. IController.Display(), if called on an already existing controller, will re-select that screen rather than creating a new one. There is also a semantic change here: CreateScreen should not select the new screen until Activate is called.

  • [WPF] IScreen must now implement an event ScreenDisposed. This and the above feature allow for internal

    deduplication of screens. Display screens (modeless editors/views) will now limit themselves to one per actual entity. In future this can be extended to other kind of screens where it makes sense; for example if we build in the reference data editor then there should only be one of it. If you really need to flush the controller cache and create two instances of one controller, calling IController<T>.Dispose() will prevent that controller from being reused.

  • [WPF] Bugfix: multiline text fields could not effectively be made readonly.

v25.1

  • [SQL] Bugfix: CreateTables.sql would not check if IDTableType already existed before trying to create it.

v25.0

  • [ORM] Cloning semantics changed. Here's what clone does now: it returns a differently-contextualised instance of your connected subgraph, by whatever means necessary. There will no longer be

    context merge failures (which can still occur from actual context merges) when cloning. Instead, entities from the cloned subgraph which were already present in the target context will have their content copied into the existing target entities, overwriting them. In short, Clone is now a safe but destructive operation.

  • [ORM] Wriggled a little way out of the context hairshirt.

  • [ORM] Attributes now have a ValueChanged event.

  • [WPF] Built some asynchrony into list/grid controls- instead of a set, you now give them a function which produces a set, and they will load it in the background with a progress bar. This also

    makes lists refreshable/reloadable and improves the general experience.

  • [WPF] Error-handling for UI actions, including all buttons/commands and all screen creation.

  • [WPF] For now, limit notifications to be text strings.

  • [WPF] Attribute fields now subscribe to ValueChanged and update when there is an orm-layer change

    (for example, when a clone occurs).

v24.1

  • [WPF] Better error handling on generated screens (makes use of the new notification system)

  • [WPF] List fixes: Add/Remove didn't refresh the display; pagers only display if necessary;

    opening & saving complex entities might be less mergefailure-prone.

  • [WPF] Display/Content fixes: DoSave() no longer requires a specific+unobtainable parameter; text

    fields are now correctly multiline.

  • [WPF] Lookup collection fields, having retrieved the set of options from a lookup factory, now

    access it as a set - paged, rather than loading it all at once.

  • [WPF] Grids within collection fields can now be separately styled (theme key TheListGrid).

  • [WPF] Multiline text fields can now be separately styled (theme key TheFieldMultilineText).

v24.0 - 17 Mar 2014

  • [ORM] Bugfix: Cloning did not work on entities with collections to which a new item had been added.

  • [ORM] True streaming queries - the enumerators produced by entity Queryables, as well as the

    enumerators of DB-backed Sets, will pull their results on demand from the datastore without buffering.

  • [ORM] Finished the infrastructure for DB-backed sets to be generated by queries, specifications and

    GetAll().

  • [SQL] Implemented a basic functional DB-backed set using SQL Server TVPs.

  • [SQL] Bugfix: multiple copies of each relationship could be generated in persistence code.

  • [SQL] Disabled GetByWhere for now as an experiment - nothing in shobiz seems to require it any longer!

  • [WPF] Some IShell methods moved into IScreen and a new ShowNotification method added

  • [WPF] Saving, generates notifications, including errors in the case of a failed save

  • [WPF] Removed Delete button from display screens

  • [WPF] Bugfix: pager controls were susceptible to a /0 error

v23.0 - 15 Mar 2014

  • [ORM] Entities' overridable InternalText property has become a GetText function and entities have gained a new Text property that can be bound to from views.

v22.2 - 14 Mar 2014

  • [WPF] Value collection fields can now contain both lists and grids.

v22.1 - 14 Mar 2014

  • [ORM] EntitySets continue to evolve. .Contains() moved from IEntitySet to IReadonlyEntitySet, and

    there's now a GetPage() function to retrieve windowed, ordered data. This is what collections use as a scalable way to access the data. There's unit test coverage for this stuff; the next step is to implement direct DB backing so that this access is efficient.

  • [WPF] Lists & grids now have overridable styles available - ListPanel, ListCell, etc. They are no longer generated screens; instead, they are created dynamically from fixed controls and the new Fields

    property metadata on their viewmodels. They respect fixed height/width settings for their visual tree hosts, though they don't have a dynamic pagesize yet. Both controls are now simple xaml instead of a weird codebehind base-class for generated code, and they use common vms/controllers; eventually they will be unified entirely into a "magic" list. This fixes some bugs, like pagers failing to update when the list contents changed.

  • [WPF] EntityDisplay has been split into EntityDisplay and EntityContent screens; Display is a fixed

    view which adds title, buttons, chrome on top of Content, which contains the fields. This allows you to override just the Content view without having to replace the rest of the UI.

v22.0 - 06 Mar 2014

  • [ORM] Cloning an entity into a context will now update an existing copy of the entity in that context

    if the existing copy has not been separately changed.

  • [ORM] New method on EntityKernel: DiscardChanges() can be used to reset an object's attributes and

    relationships to the state they were in when it was loaded. This resets the whole object graph (up to the boundary of a context), so use with care!

  • [SQL] IDatabase revamped, removing the stateful-async overloads which are no longer useful in .NET 4.5.

    Query/QueryAsync is now a completely general method which takes custom CommandBehavior; new methods Read, Buffer or Stream (with Async variants) provide more convenient access: Read produces a single value Buffer produces a list of values Stream produces a forward-only iterator with deferred execution Some of these are extension methods which require importing namespace The.SQL

  • [SQL] Bugfix: .In() specs could generate bad SQL.

  • [WPF] New namespace The.WPF.Controls; these will be common controls for consistent + themed behaviour.

    FieldControl is joined by TimePicker and DateTimePicker controls which mimic builtin DatePicker, and a new Pager control which provides generalised back/forward/pagesize settings. These controls are view-oriented APIs, intended for use like

    <EntitySummary Entity="{Binding MyProperty}" Mode="Tile"/> 
    

    rather than as model-driven templating. (The EntitySummary control is internal and unfinished). Check out The.Test.Screens\ControlTest\Window.xaml for some examples!

  • [WPF] IFieldModel.Label no longer contains formatting information like colons.

  • [WPF] Editability now propagates through any number of entities, references, collections etc.

  • [WPF] Lists and grids now have a lot more in common- they're both essentially skins over a EntitySet.

    It's now easier to create alternative presentations of that "paged entity collection" content with the same functionality. If an entity is opened from a list or grid, it is first cloned. That part isn't new functionality, but from now on, if it is saved, the changes are copied back from the edited clone to the original list. Opening from grids is modal, which prevents concurrent edits through the grid iself. Lists and grids have builtin paging, keeping only a subset in memory to save reading huge database tables. The initial implementation might not be particularly efficient, and the UI might change in future - for example, from page-switching buttons to a virtualised scrolling list. Regardless, it's no longer necessary to separately do paging or skip/take when retrieving data.

  • [WPF] Separated styles for "action" buttons and "navigation" buttons, as well as navigation links - I

    noticed that in shobiz the use of just one button style is a bit garish and hard to read.

v21.0 - 27 Feb 2014

  • [ORM] EntityKernels have a Wrapper IEntity property which is their generated-code typed entity.

  • [ORM] BindingContext renamed back to EntityContext; they really have nothing to do with UI binding.

  • [ORM] Non-null EntityContexts must now be supplied in all public API calls which Read entities. Contexts must also be supplied to calls which Create entities as well, but may be null in this case.

  • [ORM] IEntity references created by the framework are now stable - they can be compared with Is/IsNot

    if they have the same kernel. It is still possible to use SomeEntity.Metadata.WrapEntity() to create a new wrapper around the same kernel! If you do this, it will still work in framework APIs, but your own code must be written to take account of it.

  • [ORM] Entities now have a .Props member providing typed access to their dynamic propertyobjects.

  • [ORM] Bugfix: cloning an entity graph of a certain depth which used non-null contexts on mutually navigable collection properties could fail unexpectedly.

  • [SEARCH] Creating a specification with Specify() no longer requires a context. Obtaining a query or set from a

    specification with Query() or ToSet() now requires a context. Specifications themselves can be reused.

  • [WPF] IShell has a new pair of methods to implement, PushModalContent and PopModalContent. They're used by the framework in the same way as OpenModal and CloseModal which existed previously - these are just

    clearer names.

  • [WPF] The application shell is now available from The.WPF.Composition.Root. It has moved namespace to The.WPF, and should be supplied by the same "provider" config mechanism as other components. A new default "sdi"

    shell is available for rapid application prototyping.

  • [WPF] A screen token is once again required to embed subscreens - that is, IController.Embed() has become

    Embed(IShell.IScreen).

  • [WPF] The current screen is now available from IScreenModel.Screen (at least on screenmodels vended by the

    framework). It will never be null.

  • [WPF] Creating fieldmodels which display a subscreen now requires a screen token.

  • [WPF] FieldControls can now be focused with UIElement.Focus().

  • [WPF] Implemented a checked-listbox control for collection lookups.

  • [WPF] Inheritance now works with mutable lists - it will ask the user which type of object to create.

  • [WPF] Bugfix: there were internal nullreference exceptions when using reference fields. They didn't propagate, but were irritating for debuggers.

v20.0 - 21 Feb 2014

  • [ORM] Moved the in-memory set implementations, Persistence.EntitySet and Persistence.ListWrapperSet, to core, renaming them EntitySet and WrapperSet.

  • [ORM] EntitySet now has a Save() method, which will save the in-memory changes which have been accumulated to

    the database - so entities that were removed from the set will be deleted, newly added ones will be inserted, and updates will be performed for changes. This save is transactional.

  • [ORM] New public module, The.Persistence.GraphWriter, which can save entity kernels either singly or in groups

    (which will be a single transaction).

  • [SEARCH] Bugfix: ToSet was failing when used on queries generated by certain kinds of specifications.

v19.0 - 20 Feb 2014

  • [ORM] All APIs which access multiple entities in the datastore now return IEntitySet<T>/IReadonlyEntitySet<T>.

    These interfaces provide ISet<T>like containment tests and insertion, as well as inefficient - in that it pulls the set into memory - IEnumerable<T> access to their data. All framework list APIs now require sets, and they will acquire a page-based API which will guarantee efficiency.

  • [ORM] There is a Persistence.EntitySet<T> class representing an in-memory mutable set. This set type can be

    used to create collection fields (see below) and in other framework APIs when you don't want a set backed by the actual datastore.

  • [ORM] The default "forceReferenceDeletes" is now false - this means that when calling someEntity.Delete(), the operation will fail if the entity has active relationships to other entities. You can use

    entity.Delete(force:=True) if you are really, really sure.

  • [ORM] Bugfix: altering one-way relationships (where the other side is not navigable) could result in them being erroneously nulled.

  • [ORM] Bugfix: resetting a reference on the 1 side of a 1:m could result in an nullreference exception if

    anything had been removed from the m side.

  • [SEARCH] Specifications' Query() function has been replaced with a Query property. Accessing it does not execute the query.

  • [SEARCH] Specifications now have a ToSet() function. This executes the current query and provides a frozen result

    set which can be used in screens/on fields, as well as reordered, paged, etc once those APIs are public.

  • [SEARCH] New extension method IQueryable<T>.ToSet(). If you have a specification, use Spec.ToSet() rather than

    spec.Query.ToSet() - it can be more efficient and does not require importing a namespace.

  • [WPF] Renamed some APIs for better compatibility with Prism.

  • [WPF] Removed LookupFactories template (it's all generic now).

  • [WPF] Fixed some spurious warnings in EntityContent template.

  • [WPF] New fieldmodel combinator: .OfLength(int l). This changes the field's autosizing to act as if it was a

    property with a Length setting of l - you might find it more convenient to use this than size overrides in the view!

  • [WPF] New fieldmodel combinator: .Visible(). This makes a previously Hidden() field visible again. It's most

    relevant when overriding a generated screen which has some components automatically hidden, such as subcollections of entities being displayed in grids, or subreferences of entities being displayed as, themselves, references.

  • [WPF] Collection (1:m) properties on generated screens can now be removed, edited, changed, etc. The add/remove buttons are now part of the ValueCollection field, not the embedded EntityGrid screen itself.

  • [WPF] More broadly, all screen components are now fields. The previous concept of 'Subscreens' is encapsulated now by ValueReference, LookupReference, ValueCollection and LookupCollection fields. These can be created

    by the FieldModelFactory and used in custom UI just like attribute fields, with the same set of combinators and validation. This means that you can now create entity selection/embedding controls with a consistent UI - 'lookups' to just pick entities by Summary, and 'values' to also display their Content, optionally editable in-place. The next step will be to integrate this with criteria based search, importing or creating an analogue of the system used in ShoBiz.

  • [WPF] Support for BLOB properties - all attribute and relationship types are now supported in generated screens.

  • [WPF] Bugfix: Comboboxes now work as tabstops and are keyboardable in general.

  • [WPF] Bugfix: Invalid input could get erased from fields when revalidation occurred.

v18.0 - 12 Feb 2014

  • [DOCUMENTS] Improved config diagnostics.

  • [DOCUMENTS] New config setting, DocumentThrottle - the maximum number of documents which can be concurrently downloaded.

  • [DOCUMENTS] GetThumbnail is now GetThumbnailAsync, returning Task<Image>.

  • [DOCUMENTS] DownloadFile is now DownloadFileAsync, returning Task.

  • [DOCUMENTS] DownloadStream replaced with DownloadBufferAsync, returning Task<byte[]>. Internally this data

    is streamed - if streaming access is needed we will have to bring in Rx for IObservable.

  • [DOCUMENTS] Made Bitmap() GetBitmap(), and added an async version.

  • [DOCUMENTS] Bugfix: SQLDocumentStore was still throwing an exception in one of its methods.

  • [DOCUMENTS] Bugfix: SQLDocumentStore was running out of memory for large streams.

v17.0

  • [DOCUMENTS] Return null if a document is not found, rather than throwing unpredictably-typed exceptions.

  • [DOCUMENTS] SQLDocumentStore schema is now rerunnable.

  • [ORM] Currency type is now fixed to (15,2) precision.

  • [ORM] HasChanges is no longer true on entities which have been newly created but not altered at all.

  • [SEARCH] New support for arbitrarily nested .Any() clauses on queries, and restored support for complex booleans

    within .Any() clauses - also applies to NoneWith, AnyWith criteria.

  • [SEARCH] Bugfix: .As<Subclass>().SomeReference.SomeAttribute was generating invalid sql.

  • [SEARCH] Bugfix: .NoneWith could lead to incorrect joins.

  • [SEARCH] Bugfix: OrderBy was not working in some cases.

  • [WPF] Improved validation errors.

  • [WPF] Fixed checkbox alignment.

  • [WPF] Readonly fields now look a lot better.

  • [WPF] Fieldmodels no longer raise PropertyChanged if you re-set the model's value witout actually altering it.

v16.0 - 03 Feb 2014

  • [DOCUMENTS] Added FileSize metadata element.

  • [DOCUMENTS] Added IBulkDocumentStore interface for 'more direct' access to documents- it is not safe to use from distributed clients, only single-user applications.

  • [ORM] IEntityInfo now has a type parameter and a Type property (T <: IEntity)

  • [ORM] Transient entities cannot be saved

  • [ORM] Collections will now throw exceptions at you if you try to add null to them, rather than blowing up later.

  • [ORM] Bugfix: entity.Clone(context) was not cloning into the correct context.

  • [ORM] Bugfix: Clone was also not copying IDs at the correct times, leading to incorrect deduplication.

  • [ORM] Bugfix: Many thread-safety issues with cloning.

  • [SQL] Bugfix: 24 hour dates were being treated as 12-hour.

  • [WPF] Relationship property sections are now styleable - theme key ScreenSection

  • [WPF] Entities can now be deleted (maybe not a good idea??)

  • [WPF] Save (and delete) buttons work much more consistently

  • [WPF] Reference (1:1) properties on generated screens can now be removed, edited, changed, etc.

  • [WPF] It's now possible to create a custom IFieldModel<T>; inheriting from FieldModelBase<T> will give

    you most of what you need. Just make sure to template it with a view that understands FieldControl shared properties.

  • [WPF] FieldControl is no longer a subclass of ContentControl - this was misleading, as it is not meant to be used as one.

  • [WPF] Implemented [Required] flag for references.

v15.0 - 22 Jan 2014

  • [DOCUMENTS] File and Image properties now present their metadata as async functions rather than

    synchronous properties. They are asynchronous internally, and so were previously susceptible to deadlock.

  • [ORM] .HasChanges() on entities and properties is now a function instead of a property -

    it is a fairly complex and expensive operation.

  • [SEARCH] Bugfix: .In() was not working when used through relationships.

  • [SEC] We now have the very very basic start of a security framework. Applications can supply an ISecurityContext or use the provided "ntlm" context with the same appSetting/IProvider

    mechanism as is used for IEntityStore and IDocumentStore.

  • [SEC] It is no longer allowed to supply a username manually on Save() and Delete() calls.

  • [SQL] New trigger-based audit implementation. Uses ISecurityContext to determine username if

    supplied by code (which the framework does), or the database-connection username otherwise. This is another reason to use IDatabase for your custom SQL: if you use The.SQL.Composition.Root.Database, the same audit information will be added automatically.

  • [SQL] CreateTriggers template will now also fill in a CreateTriggersWithoutAudit.sql file, if

    present, which contains alternative higher-performance triggers for bulk data scenarios.

  • [WPF] IShell no longer needs to provide a username.

  • [WPF] It's no longer necessary - or possible - to use <Override> for overriding viewmodels and views.

    Plain MEF <Export> will suffice. <Override(type, key)> is now only used for dependencies which take a metadata key - IEntityInfo, ISQLPersistence, ILookupFactory, etc. Applications should not need to use it very often, if at all.

  • [WPF] IModelFactory<T> can now be exported to control the creation of generated viewmodels.

    The PartCreationPolicy of custom model factories can safely be either Shared or NonShared. Custom model factories can return any derived type of T, but if the actual model type is also custom, it should still be exported separately. This restriction may eventually be relaxed. Examples can be found in The.Test.Screens.

v14.0.2 - 20 Jan 2014

  • [DOCUMENTS] Bugfix: using .Upload() then .ID from the dispatcher was not safe in SQLDocumentStore.

v14.0 - 17 Jan 2014

  • Plugins are now configured by specifying an appsetting with the name of the provider for

    the framework to use, e.g. <add key="EntityStore" value="sql"/>. These plugins are found by adding nuget packages - The.Mongo, etc - or by exporting IProvider<T> for a custom implementation. For example, the unit tests implement an IProvider<IDocumentStore> which supplies a MockDocumentStore.

  • New package The.SQL which provides the SQL entitystore and documentstore.

  • [ORM] Entity.Clone() no longer always requires a database call - previously it was impossible to clone entities which had not yet been saved.

  • [ORM] Even more fixes to relationship saves and HasChanges

  • [ORM] New setting LogPersistence. It works similarly to LogSQL, logging the sequences of

    read/write/query operations which the framework generates.

  • [SQL] SQL documentstore no longer uses Agcom.Images, but its own implementation of a basic file DB.

    It's now efficient enough to use in SHOBiz.

  • [SQL] The current IDatabase is now available through SQL.Composition.Root instead of The.SQL.DB

  • [SQL] new IDatabase.GetTransactionAsync and ITransaction.CommitAsync() methods

v13.4 - 14 Jan 2014

  • [ORM] Bugfix: Entity.Copy() was not behaving as advertised.

  • [ORM] Bugfix: removing an entity from a collection property and then adding it back had issues.

  • [WPF] Calling Invalidate() in validation rules is now a thread-safe operation. It will cause the

    invalidated field model to have validation scheduled, rather than performed immediately. The use case is to easily implement mutual validation.

v13.3 - 13 Jan 2014

  • [ORM] You can now use a context similarly to a unit of work, calling .Save() on it to save all its

    guaranteed-unique entities - which can in this context be considered analogous to CQRS commands - in a single transaction.

  • [ORM] Bugfix: Relationships to Transient entities were not being generated correctly.

  • [ORM] Length/Precision were seemingly never implemented for Decimal, only for Currency. Now they are.

  • [WPF] Bugfix: DateSpecification.>= now works correctly (other permutations were already correct).

v13.2 - 13 Jan 2014

  • [WPF] >=/<= criteria now supported for Dates and Datetimes

v13.1 - 10 Jan 2014

  • [ORM] Bugfix: HasChanges now covers more cases, and is not susceptible to stack overflow.
  • [ORM] Bugfix: There was a race condition which could lead to context merge failures during searches.
  • [WPF] Setting someFieldModel.Value in code will now trigger a gui update.
  • [WPF] FieldControls have a new ContentSizeGroup property, which can be used to yoke autosizing for multiple fields together or allow one to grow indefinitely.

v13.0

  • [DOCUMENTS] Experimental SQL Server backend The.Documents.SQL - not integrated into shobiz yet, I will

    need to add some database scripts.

  • [LINQ] .Skip(n) now interacts correctly with .Count()

  • [LINQ] Null checks are now supported for references, so you can now write queries like this:

    Human.Query.Where(Function(h) h.Wears IsNot Nothing AndAlso h.Wears.InFashion = True)
    

    or this: From h In Human.Query Where h.Wears Is Nothing OrElse Not h.Wears.InFashion = True and they work through reference chains, so you could write a spec like this: With Farm.Specify .Owner.Wears.IsNull() .Owner.Or.Wears.InFashion.EqualTo(True) End With

  • [MODEL] Removed modelled Methods - which were not fully implemented, so this doesn't break anything.

  • [MODEL] It is no longer supported for subclasses of a common abstract class to each have a different relationship with the same property name. It is now supported to retrieve a T<:U as

    a U, cast it to T, and then access its relationships.

  • [ORM] Significant performance improvements.

  • [ORM] Reads are now serialisable like writes, and optionally transactional.

  • [ORM] The IPersistence.vb template is gone.

  • [ORM] Bugfix: relationship indexes were still backwards, although not as backwards as before.

  • [ORM] Bugfix: HasChanges was not correctly reset to false after relationship saves.

  • [ORM] Bugfix: When performing a series of relationship modifications between entities, there were multiple ways in which they could fall out of sync.

v12.2 - 27 Dec 2013

  • [ADDIN] WPF templates are generated with all the imports they need, rather than assuming VB auto-imports.
  • [ADDIN] Fixed crash bug when creating override classes for new entities.
  • [WPF] Added Time/DateTime fields, as well as TimePicker/DateTimePicker controls that can be used more generally.
  • [WPF] More VM components are now overridable.
  • [WPF] Fixed "ElementName=EditableContent" binding errors.

v12.1 - 26 Dec 2013

  • [ADDIN] You can now use a top-level GenOnly project instead of a GenOnly folder.

    Still looking for a better name for GenOnly!

  • [ADDIN] Custom templates no longer appear multiple times in the template selector dialog.

  • [ADDIN] Template selector dialog is considerably less weird. Esc, Enter, etc now work. Shift-clicking

    will check/uncheck namespaces together. And finally, template selection is saved in the model.

  • [DOCUMENTS] The MongoDB document store implementation is now an optional dependency, in a separate package.

    This is in preparation for writing other implementations.

  • [MODEL] Removed disused "same class" relationship flag.

  • [MODEL] Fixed an issue where exotic combinations of attribute flags (reference type + required + nullable)

    would generate invalid code.

  • [WPF] Double-clicking on non-selecting areas of an entitylist will no longer cause a crash.

v12.0 - 23 Dec 2013

  • [DOCUMENTS] File and Image attributes now have fieldmodels. You can create and validate them the same way

    as any other attribute (e.g.: FieldModelFactory.Create/CreateFile/CreateImage). The associated GUI controls need some work, but do have functional upload/download buttons.

  • [DOCUMENTS] Image thumbnail quality increased. Enjoy GDI's finest bicubic interpolations!

  • [DOCUMENTS] Thumbnails now correctly preserve aspect ratio and clamp to the smaller of the max width/height you supply.

  • [SEARCH] Specifications can now be composed either top-down or bottom-up. Wherever you previously

    acquired a sub-specification and then mutated it - .Or(), .AnyWith(), etc - it is now possible to supply an existing specification instead. These overloads do NOT return the added sub-specification, but the existing specification, similarly to the existing fluent API.

  • [SEARCH] Added .In() criteria, which asserts that the property is in some sequence. Example usage:

    Human.Specify.ID.In({someID, someOtherID})
    
  • [SEARCH] Added .And() subspecifications, which work like the Or() subspecifications. However, if you

    use both .Or() and .And() on a single top-level spec, no useful ordering would be guaranteed, so this is not allowed.

  • [SQL] Refactored QueryTranslator to use true joins, INNER or LEFT OUTER as appropriate. Emitted SQL

    is simpler and faster, and no longer contains gratuitous sub-selects.

  • [SQL] Attributes now translate to expression-valued SQL at any point in a query. This fixes numerous bugs related to navigating relationships and enables complex link-following queries like this:

     Dim hatsOfPetOwnersByAge = From h In Hat.Query
                                Where Not h.InFashion
                                Where h.WornBy.Owns.Animals.Any(Function(a) a.Name = "Polly")
                                Order By h.WornBy.Age, h.Name Descending
    
  • [SQL] Added support for <arbitrary enumerable>.Contains(some property).

  • [SQL] Added support for Nullable.HasValue and Is Nothing/IsNot Nothing/== null/!= null.

  • [SQL] Bugfix: 1:M relations had UNIQUE index constraints on the wrong sides

  • [WPF] New system: Screen display and layout are now done by global styles. Themes can be overriden

    in whole (by substituting a resource dictionary that uses Themes.Keys) or in part (by merging a resource dictionary that redefines certain keys). There are two builtin themes: Tabular and Hercules.

  • [WPF] Combined Edit and View into a single "Display" screen. Use <entity>Display.Create(e, isEditable) to set whether you want it to be for edit screen or not. It still uses the same EntityContent model.

  • [WPF] EntitySummary controllers are now accessible, and Summary screens can be used/overridden directly.

  • [WPF] Moved around fieldmodel factory methods - some parameter orders changed, but you have more options.

v11.0 - 17 Dec 2013

  • updated to .NET framework 4.5.1

  • listviews can now be overridden

  • adhoc IScreenModel overrides are now type-safe if you use the new overload controller.Create<T>

  • IFieldModel factory improvements - nominal types, self-lensing; this includes access to

    typed fieldmodel values, including the ability to set the modelvalue and have it trigger events

  • simplified IShell - application no longer needs to provide any kind of special modal windows

  • implemented a field type for Text properties, with a larger multi-line textbox - in future we can add capabilities like pop-out editing

  • implemented a field type for Currency properties, with symbols and stricter parsing

  • file/image api is now consistent about its [non-]use of async; only Image/File.Upload remains

  • autonums are now a bit better supported - if you mark a column as Identity, it will not

    generate a setter, and they will not be editable in generated screens.

  • embedding no longer requires a screen token - you can just create controllers and Embed()

    them to indicate that they are not in control of an actual screen. Display() and Replace() still give them control over a screen.

  • TemplateManager now lets you specify whether it will search for mvvm mismatches and fail-fast

  • EntityBase.Save and .Delete can now be overridden

  • attributes now have a TrySetValue method to parse text into a value

  • bugfix: sql-writing transactions were not getting closed

v10.2.2 - 12 Dec 2013

  • bugfix: documentstore would block if used from the ui thread

v10.2.1 - 11 Dec 2013

  • bugfix: weird edge-case where circular references in collections could stack overflow

v10.2 - 10 Dec 2013

  • saves are now transactional - the framework is finally multi-user safe
  • saving is dozens-to-hundreds of times faster

v10.1 - 09 Dec 2013

  • simplified how EntityKernels are constructed and turned into typed entities using IEntityInfo.Wrap

  • whether or not they are nullable, attributes now still allow nulls in the database

    (unless you have enabled 'Enforce non-nullability in SQL'). marking an attribute 'Nullable' now only alters whether you can use it as null in code, and the behaviour of 'Required'

  • added File and Image properties which provide lazy streaming access to remote blobs. File

    represents arbitrary data, and Image adds height/width properties as well as thumbnailing.

  • internally uses an IDocumentStore facility for storing schemaless structured data, which

    can be accessed via The.Composition.Root and can be replaced with [Export]/[Override]. the default implementation uses a MongoDB instance at ConnectionStrings["The Documents"].

  • bugfixes: applied 'LegacyOnly' in more templates

v10.0.2 - 05 Dec 2013

  • bugfix: transient entities were crashing templates

v10.0 - 03 Dec 2013

  • merged Version and Timestamp properties

  • fields now resize in groups - attributes with the same Length will size together

  • implemented Display Order

  • added Required flag for attributes (relationships already had it)

  • completed the separation of Properties into Attributes and Relationships

  • removed Text on attributes. Parse() will convert strings to values of the attribute's data type

  • implemented attribute Default values; making use of Required and Default will improve validation

  • changed entity-load API around a bit. GetQuery and GetSpecification are now Query and Specify;

    specification.Get is also named Query, for consistency. hopefully this will make it easier to tell what the functions are actually returning - unlike the other Get functions, they don't produce entities directly!

  • new Copy function on entities which produces a new entity with the same attributes

  • began separating HOBS support out so that it can be moved into a schema extension mechanism

v9.1 - 29 Nov 2013

  • field heights and widths adjusted slightly to be better embedded in non-generated screens
  • bugfix: broke a cycle in change-tracking

v9.0 - 28 Nov 2013

  • WPF lookup factories are now separate to lookup viewmodels (and separately overridable)

  • WPF field validation system for entity attributes, more fully detailed in validation.txt.

    validation is extensible by overriding viewmodels and applying combinators, or by overriding views and prepending ValidationRules.

  • overriding is now done with the Override attribute, which takes an optional and

    unique key string to specify override context - such as a specific property or entity. for example, you can override lookup for a specific property only with [Override(GetType(ILookupFactory(Of Dog, Human)), "BestFriend")] or for all lookups of the correct type with [Override(GetType(ILookupFactory(Of Dog, Human)))]

  • unified generated screen elements and custom runtime-generated fields, replacing the old

    "autoui". FieldModelFactory is the equivalent of the previous PropertyViewModelFactory, and you display IFieldModels by binding to a The.WPF.Views.FieldControl.

  • new flag on columns, "Legacy Only" - suppresses generation for everything except SQL

  • IDatabase no longer requires you to specify a commandbehaviour for queries

  • bugfix: without a way to block on modal screens in IShell, grid controllers were doing the wrong thing with the subwindows they open, which caused shobiz to lack

    any way to close its entity-edit views.

  • bugfix: a race condition in EntityBaseInfo was causing crashes if an application had a threaded startup process. fixed using Lazy<T>.

  • bugfix: captions were being generated incorrectly for relationships without custom names

  • bugfix: changing an entity's reference's values will cause the entity to HasChanges()

v8.1 - 22 Nov 2013

  • support for concrete inheritance (that is, inheritance from non-abstract entities)
  • WPF date picker fields
  • WPF relationship lookup fields, with overridable factory methods
  • WPF view overrides

v8.0 - 20 Nov 2013

  • true nullability support; a nullable date column will produce a NullableDateObject with a value of type Date?. nullable properties default to null and will store actual nulls

    in the database (rather than e.g. 1/1/1800 or ""). by default, non-nullable properties are still nullable in the database; there's a model-level setting for this, but turning it on requires recreating the application's database, which is not always possible.

  • query and criteria support for IsNull/NotNull

  • GUIDs are now exposed as GUIDs rather than strings

  • new pluralisation module for automatically determining english noun plurals

  • improved accuracy of code-generation progress bars

  • WPF unit tests

  • WPF grids support inheritance

  • WPF display/edit forms are now marginally usable (but still missing important features)

  • api: you can set non-nullable string properties to Nothing and they will be String.Empty

  • bugfix: non-nullable dates are no longer stored as null

v7.0 - 14 Nov 2013

  • WPF screen generation: entity views, editors, lists and grids

  • application supplies an IShell to control screens, dialogues, etc

  • overridable viewmodels at either the screen or field level

  • properties are now IComparable and IComparable<T>

  • criteria improvements:

    - criteria .AnyWith and .NoneWith replace the predicated forms of Any and None; they return 
      sub-specifications which can be used to existentially or universally quantify the query
    - the query returned by .Get on a specification can be reused
    - GenericGetByWhere is no longer public api
    
  • bugfix: HasChanged on saved entities and on collections

  • bugfix: collection deletes now work consistently

  • bugfix: no AggregateException crashes during threaded startup

  • bugfix: sql was quoting table names only some of the time

  • bugfix: reenabled createdBy/On/etc

v6.0 - 04 Nov 2013

  • harmonised all namespaces with DLL/nuget names

  • removed use of applicationSettings

  • replaced internal static configuration with MEF composition

  • generator improvements: considerably faster, supports codebehinds, separated GUI and codegen, has progress bar

  • query/criteria improvements:

    - added .FirstOrDefault() and .SingleOrDefault()
    - .None() on collections, counterpart to .Any()
    
  • bugfix: ClassType no longer necessary for non-hierarchical entities

v5.0.2 - 30 Oct 2013

  • bugfix: CreateTriggers template

v5.0.1 - 29 Oct 2013

  • bugfix: empty TextBoxBasedPropertyObjectViewModel would raise NullReferenceException

v5.0 - 28 Oct 2013

  • incorporated the generation-time model into the core framework, to keep templates in sync etc
  • templates are now written in T4, with design-time typechecking
  • the generator now does reflection in a separate AppDomain, avoiding file locks and temp assemblies
  • bugfixes and added operators for EntityQuery<T>s
  • bugfixes and new tests for reference-saving
  • .Count and .Any() on query/specification searches are now Efficient
  • strict binding-context enforcement in anticipation of the day when it will be relevant
  • began using internal namespaces
  • removed boxing in propertyobjects - improves entity-manipulation performance
  • removed unnecessary dependencies of the codegen addin so it works with VS2010 again

v4.1 - 24 Oct 2013

  • bugfix: un-initialised GuidObjects no longer prevent an object from saving

  • Date and Time attributes now generate genuine Date/Time SQL columns, and correctly truncate data

    (Time attrs are represented in .net code as a TimeSpan rather than a DateTime)

  • queries now support string.Length, string.Contains(), collection.Any()

  • criteria now support string.Contains(), collection.Any(), collection.Any(predicate)

  • specifications now support circular references, many-to-many, etc. using Lazy<T>

  • The Generator will wait more patiently for solution files to finish loading

  • IDatabases now provide a descriptive/informational server and name

  • improved the intellisense on entities - Comment works for entities, attributes and relationships

v4.0 - 23 Oct 2013

  • VS2013 is now supported

  • bugfix: made the behaviour of reference deletes more reliable (including working with inheritance)

  • bugfix: change-checking now works through collection references

  • specifications now support .ID

  • queries now support .First() and .Single()

  • various collections which were exposed as IEnumerable<T> or some custom List-like object are now

    exposed as IList<T>, with fast .Count and encapsulated dynamism

  • EntityCollection and EntityReference are now generic (EntityCollection<T> and EntityReference<T>)

  • GetById, GetAll and GetByWhere are also generic

  • fully custom names can now be set for relationship attributes, without mandating -Ref and -Col

  • entities are now a typed wrapper around a dynamic kernel, which is an ID and a bag of attributes this has many implications for the public API. too many API changes to list, in fact. generally

    speaking, the IEntity itself now only has typed properties corresponding to its attributes; the 'Info' properties are accessible via its metadata, and the 'Obj' properties via its kernel for general CRUD use, it shouldn't be necessary to access the dynamic kernel. however, it is available via .Kernel for 'advanced' purposes such as runtime dynamism. the API has been cleaned up in many places so that operations which used to require generic/dynamic access can now be done using only the typed entity wrappers. other API cleanups include minimised use of Shadows, removal of redundant or unimplemented functions in the direct(generated) API, and exposure of interfaces rather than implementation details in most cases.

v3.2.1 - 18 Oct 2013

  • bugfix: re-enabled cloning

v3.2 - 17 Oct 2013

  • further performance improvements

    parallelisation of queries to avoid latency
    optimised cross-referencing
    

v3.1 - 16 Oct 2013

  • bugfixes
  • large performance improvements (save 2x speedup, load 3x speedup)

v3.0 - 15 Oct 2013

  • specifications now expose the generated IQueryable, allowing you to add clauses (such as Skip()/Take()) and to stream it
  • unit tests! consequently, quite a few bugfixes
  • data layer restructured, with improved reliability and performance
  • persistence is now completely lock-free, probably
  • new "IDatabase" sql abstraction for safe direct access to the database; SQLPersistence.Database will give you one
  • GetAll/GetWhere now return IEnumerables; they are in some cases streamed directly out of the database and in others crystallised to a list
  • updates are now minimal, sending only the changed data to the server
  • new "LogSQL" setting, which does what you would expect it to do
  • username may be omitted on CRUD Saves and Deletes, in which case it will use the Windows username (not always what you want!)
  • datalevel is gone, replaced with a simple lazy-loading of relationships. the next step will be to provide some way to mark aggregates for eager loading.

v2.0 - 07 Oct 2013

  • All libraries now CLS-compliant

  • rescued Access backend from bitrot and moved it to a separate package

  • changed some template names to clarify what they are actually for (e.g. GenSQL -> SQLPersistence)

  • moved entity metadata to a separate template and simplified the Foo__Gen -> partial hierarchy

  • removed (public) "datalevel" concept; this will be handled automatically under the covers

  • simple CRUD Create API - this might not cover all cases but should be the only one necessary for normal use

    EntityName.Create([context])
    
  • simple CRUD Read API - these are now the only public ways to access data:

    EntityName.GetAll([context])
    EntityName.GetByID(id, [context])
    EntityName.GetByWhere(clause, `[context])	<-- this one will only show up if you're using the SQL module`
    EntityName.GetQuery([context])
    EntityName.GetSpecification([context])
    
  • renamed model concepts to refect generally used terminology

    "Class" `->` "Entity"
    "Metaclass" `->` "Dynamic Entity"
    "Property" `->` "Attribute"
    "Association" `->` "Relationship"
    "Info" `->` "Metadata"
    

v1.1.2 - 03 Oct 2013

  • The default value for the 'StorageType' setting has been updated to match the new generated class name

v1.1.1 - 03 Oct 2013

  • Specification template output now compiles under VS2010 and associated MSBuild version

v1.1 - 02 Oct 2013

  • criteria-based search API - it's a strongly-typed wrapper over queries, using only tested expressions

  • improved queries

    support for inheritance
    support for relations with custom names
    substring and arithmetic support
    
  • use of Diagrams is now optional

  • more readable templates (and template output)

  • class explorer niceties

    entity defaults to a DataTable inheriting from BaseClass
    allow deleting [empty, class] nodes
    close window by pressing Esc
    removed some unimplemented options
    
  • (re??)implemented the Long column type

  • fixed the Decimal column type

v1.0.1 - 25 Sep 2013

  • Text entity attributes generate nvarchar(max) columns instead of nvarchar(0)
  • Transient entity attributes have no SQL generated

v1.0 - 21 Sep 2013

  • first versioned release
  • nuget packages (Core, Forms, WPF, Reports)
  • no longer requires a source copy in every project

31/08/2013 - 21/09/2013 pre-1.0

  • common codebase extracted from SHOBiz, WotzNext and MineFED
  • heavy refactoring
  • multiple template directory support
  • no longer creates temporary files in source tree
  • addin thread-safety
  • reduced dependencies
  • modern sql column types
  • T4 support
  • VS2012 support
  • does not require VS2010, at the cost of 4.0 support for the addin - this could be changed back