Kephas.Data
11.1.0
Prefix Reserved
dotnet add package Kephas.Data --version 11.1.0
NuGet\Install-Package Kephas.Data -Version 11.1.0
<PackageReference Include="Kephas.Data" Version="11.1.0" />
paket add Kephas.Data --version 11.1.0
#r "nuget: Kephas.Data, 11.1.0"
// Install Kephas.Data as a Cake Addin #addin nuget:?package=Kephas.Data&version=11.1.0 // Install Kephas.Data as a Cake Tool #tool nuget:?package=Kephas.Data&version=11.1.0
Data
Introduction
Data is one of the most important parts of an application. To leverage working with it, Kephas provides an abstract data infrastructure which allows data manipulation (CRUD), validation and support for various behaviors.
The general architecture
All data operations are performed through a data context. The data context is responsible for holding and managing a local cache of data and for instantiating [[commands|Data-commands]]. The commands are actually the performers of data operations, integrate data behaviors, and are tightly coupled to the data context that created them.
Data contexts are created by a data context factory, which is a [[singleton application service|Application-services]], by providing a data store name. The factory uses configured data store information and associated services to get it and to initialize the data context.
The data context
The data context is the entry point in regard to data operations. Its main responsibilities are:
Query the data and retrieve the results. There are no restrictions regarding the implementation of the data querying, so it's up to the implementation to use, for example, a first or a second level cache. All the information controlling how the querying should be performed may be specified in the
queryOperationContext
parameter, which is an expando that can be customized freely.Create the commands. As explained in the following, the strategy for creating the commands will choose the most appropriate one for the calling data context.
Provide entity information. This is information attached to each entity in the internal cache regarding its ID, change state, original data, and many more.
Attach and detach entities. These operations add/remove entities to/from the internal cache.
Apart from these, the data context:
is a contextual object: the consumers may access the [[ambient services|Application-Environment-and-Lifetime-Management#ambient-services]] and use the data context as an [[expando|Dynamic-expandable-objects-(expandos)]] object, dynamically adding and accessing values to it/from it.
is initializable and disposable: implements the
IInitializable
andIDisposable
interfaces to control its lifetime.
The data context factory
Data contexts are dependent on initialization data, which typically contains at least data store connection information. Due to the fact that multiple physical data stores may be served by the same data context implementation and that by design, at one time, a data context instance may be connected to a single physical data store, there must be a factory service that creates a data context for a given connection. This is the data context factory application service.
- CreateDataContext(dataStoreName, [initializationContext]): IDataContext: This is the only method of the factory service which creates a data context instance and initializes it.
- dataStoreName: indicates the name of the data store. This identifies typically an entry in the configuration where connection information and other initialization data is provided.
- initializationContext: provides contextual information for data context initialization.
Note: The consumer of the CreateDataContext method takes the full responsibility of disposing correctly the received data context.
The data commands
The [[data commands|Data-commands]] extend the data context functionality beyond the minimalist one defined by the IDataContext
interface. Kephas provides built-in commands for the following data operations:
- Create entity
- Delete entity
- Persist changes
- Discard changes
- Find by ID
- Find by criteria
These operations provide the basic infrastructure for data manipulation, but for some scenarios this might not be enough. For example, update commands fired against all entities matching a specific criteria, calling stored procedures, or supporting all kinds of upsert variations are specific cases where there is no built-in support. With Kephas, the developer is free to define as many commands as needed, tailored for specific needs and data stores of all kinds. For a step-by-step tutorial, check the [[data commands|Data-commands]] page.
The IDataCommand
interface and DataCommandBase
base class
A data command has basically only one method: ExecuteAsync
, which takes an operation context as parameters and returns a promise (task) of a result. The base interface to be implemented by a command is IDataCommand
, which has its generic flavor IDataCommand<TOperationContext, TResult>
. However, to ease the definition of commands, a base class DataCommandBase<TOperationContext, TResult>
is provided, where only the generic ExecuteAsync method should be implemented.
public interface IDataCommand
{
/// <summary>
/// Executes the data command asynchronously.
/// </summary>
/// <param name="operationContext">The operation context.</param>
/// <param name="cancellationToken">The cancellation token (optional).</param>
/// <returns>
/// A promise of a <see cref="IDataCommandResult"/>.
/// </returns>
Task<IDataCommandResult> ExecuteAsync(IDataOperationContext operationContext, CancellationToken cancellationToken = default(CancellationToken));
}
/// <summary>
/// Contract for data commands, with typed operationContext and result.
/// </summary>
/// <typeparam name="TContext">Type of the operation context.</typeparam>
/// <typeparam name="TResult">Type of the result.</typeparam>
public interface IDataCommand<in TOperationContext, TResult> : IDataCommand
where TOperationContext : IDataOperationContext
where TResult : IDataCommandResult
{
/// <summary>
/// Executes the data command asynchronously.
/// </summary>
/// <param name="operationContext">The operation context.</param>
/// <param name="cancellationToken">The cancellation token (optional).</param>
/// <returns>
/// A promise of a <see cref="IDataCommandResult"/>.
/// </returns>
Task<TResult> ExecuteAsync(TOperationContext operationContext, CancellationToken cancellationToken = default(CancellationToken));
}
Steps in implementing a data context command
Define the command application service contract
The data context uses composition to get an instance of the command to use, so the commands will provide an application service contract and one or more service implementations.
Multiple command implementations may be provided targeting specific data context implementations (different data context implementations may be provided for relational databases, NoSQL databases, or graph databases), so that the targeted data context finds the appropriate command to use. For example, a MongoDBFindOneCommand
will indicate that it targets a MongoDBDataContext
.
Note: When the data context creates the command through composition, it must get a new instance, otherwise unexpected behavior may occur. Therefore it is strongly discouraged to mark the application service contracts as shared.
Note: Together with the application service contract, the specific operation context type (where the input parameters will be provided) and the specific expected result type will be defined, if the command requires it. They must specialize the
IDataOperationContext
andIDataCommandResult
respectively.
/// <summary>
/// Contract for find commands retrieving one entity based on a predicate.
/// </summary>
[AppServiceContract(AllowMultiple = true,
MetadataAttributes = new[] { typeof(DataContextTypeAttribute) })]
public interface IFindOneCommand : IDataCommand<IFindOneContext, IFindResult>
{
// AllowMultiple = true indicate that multiple implementations may be provided.
// DataContextTypeAttribute as metadata attribute indicate that
// the implementations may specify a target data context type.
}
/// <summary>
/// Interface for data operation contexts of the <see cref="IFindOneCommand"/>.
/// </summary>
public interface IFindOneContext : IDataOperationContext
{
/// <summary>
/// Gets the criteria of the entity to find.
/// </summary>
Expression Criteria { get; }
/// <summary>
/// Gets the type of the entity.
/// </summary>
Type EntityType { get; }
/// <summary>
/// Gets a value indicating whether to throw an exception if an entity is not found.
/// </summary>
bool ThrowIfNotFound { get; }
}
/// <summary>
/// Generic interface for data operation contexts of the <see cref="IFindOneCommand"/>.
/// </summary>
/// <typeparam name="TEntity">Type of the entity.</typeparam>
public interface IFindOneContext<TEntity> : IFindOneContext
{
/// <summary>
/// Gets the criteria of the entity to find.
/// </summary>
/// <remarks>
/// Overrides the untyped expression from the base interface
/// to provide LINQ-support.
/// </remarks>
new Expression<Func<TEntity, bool>> Criteria { get; }
}
/// <summary>
/// Interface for the find result.
/// </summary>
public interface IFindResult : IDataCommandResult
{
/// <summary>
/// Gets the found entity or <c>null</c> if no entity could be found.
/// </summary>
object Entity { get; }
}
Provide data context specific implementation of the command
After the service contract was defined, the service implementing it is created. For convenience, the base class DataCommandBase<TOperationContext, TResult>
may be used.
Important: Do not forget to annotate the command service with the targeted data context type. The match is not exact, but done on a compatibility basis. This means that if a data context instantiating a command may find multiple being compatible with it (target compatible types, like the base type
DataContextBase
). The current strategy will choose the command targeting the most specific data context.
/// <summary>
/// Base class for find commands retrieving one result.
/// </summary>
[DataContextType(typeof(DataContextBase))]
public class FindOneCommand : DataCommandBase<IFindOneContext, IFindResult>, IFindOneCommand
{
//... implement the command execution
}
// The command below targets a very specific data context, the MongoDataContext,
// while the one above should work for all specializing the `DataContextBase`.
/// <summary>
/// Command for persisting changes targeting <see cref="MongoDataContext"/>.
/// </summary>
[DataContextType(typeof(MongoDataContext))]
public class MongoPersistChangesCommand : PersistChangesCommand
{
//... implement the command execution
}
Provide data context extension methods to make command consumption easier
Even if we are ready with the new command, it is not very handy to use it. Here is how we would use it now:
var command = dataContext.CreateCommand<IFindOneCommand>();
var findContext = new FindOneContext
{
Criteria = criteria,
ThrowIfNotFound = false,
}
var result = await command.ExecuteAsync(findContext).PreserveThreadContext();
var foundEntity = result.Entity;
// yupee, got the entity! but it was a loooong way to get there :(.
So, to achieve the simplicity of simply calling the command on the data context, the next step would be to provide an extension method to wrap up all this stuff.
public static class DataContextExtensions
{
//...
public static async Task<T> FindOneAsync<T>(
this IDataContext dataContext,
Expression<Func<T, bool>> criteria,
bool throwIfNotFound = true,
CancellationToken cancellationToken = default(CancellationToken))
where T : class
{
Requires.NotNull(dataContext, nameof(dataContext));
Requires.NotNull(criteria, nameof(criteria));
var findOneContext = new FindOneContext<T>(dataContext, criteria, throwIfNotFound);
var command = (IFindOneCommand)dataContext.CreateCommand(typeof(IFindOneCommand));
var result = await command.ExecuteAsync(findOneContext, cancellationToken).PreserveThreadContext();
return (T)result.Entity;
}
}
Now we can use the defined command as if it was a method of the data context:
var foundEntity = await dataContext.FindOneAsync<Customer>(
c => c.Name == "John" && c.FamilyName == "Doe",
throwIfNotFound: false).PreserveThreadContext();
// way better :)
Synchronous commands
Most data operations are by design asynchronous, but some do not need this overhead, for example because they work with data in the local cache, like marking entities for deletion or discarding the in-memory changes. For such data commands, they need to implement the ISyncDataCommand
interface or, more comfortable, specialize SyncDataCommandBase
.
Securing the data
Entity types may be secured by decorating them with the [SupportsPermission] attribute.
Example:
/// <summary>
/// The customer entity type.
/// </summary>
[SupportsPermission(typeof(IAdminPermission))]
public interface ICustomer : ...
{
}
Note: If a mixin declares supported permission types, all entity types inheriting that mixin will support those permissions, too.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Kephas.Abstractions (>= 11.1.0)
- Kephas.Collections (>= 11.1.0)
- Kephas.Data.Abstractions (>= 11.1.0)
- Kephas.Injection (>= 11.1.0)
- Kephas.Logging (>= 11.1.0)
- Kephas.Operations (>= 11.1.0)
- Kephas.Reflection.Dynamic (>= 11.1.0)
- Kephas.Security.Permissions (>= 11.1.0)
- Kephas.Serialization (>= 11.1.0)
- System.Linq.Expressions (>= 4.3.0)
- System.Linq.Queryable (>= 4.3.0)
-
net6.0
- Kephas.Abstractions (>= 11.1.0)
- Kephas.Collections (>= 11.1.0)
- Kephas.Data.Abstractions (>= 11.1.0)
- Kephas.Injection (>= 11.1.0)
- Kephas.Logging (>= 11.1.0)
- Kephas.Operations (>= 11.1.0)
- Kephas.Reflection.Dynamic (>= 11.1.0)
- Kephas.Security.Permissions (>= 11.1.0)
- Kephas.Serialization (>= 11.1.0)
- System.Linq.Expressions (>= 4.3.0)
- System.Linq.Queryable (>= 4.3.0)
NuGet packages (12)
Showing the top 5 NuGet packages that depend on Kephas.Data:
Package | Downloads |
---|---|
Kephas.Data.Client
Provides the infrastructure for the client area of the data flow. Typically used areas and classes/interfaces/services: - Queries: IClientQueryProcessor. Kephas Framework ("stone" in aramaic) aims to deliver a solid infrastructure for applications and application ecosystems. |
|
Kephas.Data.Model
Provides a modeling API framework for data. Typically used areas and classes/interfaces/services: - IEntityType, IKey. - Dimensions: Client (area), Domain (area). - AttributedModel: EntityAssemblyAttribute, EntityTypeAttribute, KeyAttribute, NaturalKeyAttribute, PrimaryKeyAttribute. - Analysis: ModelRefPropertiesBehavior. Kephas Framework ("stone" in aramaic) aims to deliver a solid infrastructure for applications and application ecosystems. |
|
Kephas.Data.IO
Provides services for the data import/export (input/output). Typically used areas and classes/interfaces/services: - DataStreams: IDataStreamReader, IDataStreamWriter. - Export: IDataExportService. - Import: IDataImportService, IDataImportBehavior. Kephas Framework ("stone" in aramaic) aims to deliver a solid infrastructure for applications and application ecosystems. |
|
Kephas.Data.Endpoints
Adds messaging endpoints for data services. The endpoints will work if Kephas.Messaging is referenced and the IMessageProcessor is used for processing the messages. Typically used areas and classes/interfaces/services: - PersistChangesHandler, QueryHandler, DataSourceHandler. Kephas Framework ("stone" in aramaic) aims to deliver a solid infrastructure for applications and application ecosystems. |
|
Kephas.Data.MongoDB
Provides the MongoDB implementation for data context and associated commands. Typically used areas and classes/interfaces/services: - MongoDataContext. Kephas Framework ("stone" in aramaic) aims to deliver a solid infrastructure for applications and application ecosystems. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
11.1.0 | 4,357 | 4/13/2022 |
11.1.0-dev.4 | 143 | 4/6/2022 |
11.1.0-dev.3 | 140 | 3/30/2022 |
11.1.0-dev.2 | 138 | 3/23/2022 |
11.1.0-dev.1 | 143 | 3/23/2022 |
11.0.0 | 4,153 | 3/11/2022 |
11.0.0-dev.7 | 149 | 3/7/2022 |
11.0.0-dev.6 | 153 | 2/28/2022 |
11.0.0-dev.5 | 134 | 2/26/2022 |
11.0.0-dev.4 | 135 | 2/24/2022 |
11.0.0-dev.3 | 134 | 2/23/2022 |
11.0.0-dev.2 | 140 | 2/18/2022 |
11.0.0-dev.1 | 141 | 2/7/2022 |
10.3.0 | 3,872 | 1/18/2022 |
10.2.0 | 3,138 | 12/3/2021 |
10.1.0 | 7,173 | 11/23/2021 |
10.1.0-dev.7 | 199 | 11/17/2021 |
10.1.0-dev.6 | 180 | 11/16/2021 |
10.1.0-dev.5 | 172 | 11/10/2021 |
10.1.0-dev.4 | 194 | 11/8/2021 |
10.1.0-dev.3 | 157 | 11/8/2021 |
10.1.0-dev.2 | 179 | 11/4/2021 |
10.1.0-dev.1 | 166 | 11/3/2021 |
10.0.1 | 3,180 | 10/16/2021 |
10.0.0 | 3,129 | 10/13/2021 |
10.0.0-dev.4 | 166 | 10/13/2021 |
10.0.0-dev.3 | 177 | 10/11/2021 |
10.0.0-dev.2 | 227 | 10/8/2021 |
9.3.4 | 2,960 | 8/25/2021 |
9.3.3 | 3,002 | 8/25/2021 |
9.3.2 | 2,939 | 8/24/2021 |
9.3.1 | 2,842 | 8/12/2021 |
9.3.0 | 3,000 | 8/12/2021 |
9.2.0 | 3,061 | 6/17/2021 |
9.1.0 | 2,974 | 6/17/2021 |
9.1.0-dev.9.1 | 212 | 5/28/2021 |
9.1.0-dev.9 | 203 | 5/26/2021 |
9.1.0-dev.8 | 192 | 5/26/2021 |
9.1.0-dev.7.1 | 194 | 5/17/2021 |
9.1.0-dev.7 | 205 | 5/17/2021 |
9.1.0-dev.6 | 186 | 4/28/2021 |
9.1.0-dev.5 | 205 | 4/23/2021 |
9.1.0-dev.4 | 191 | 4/21/2021 |
9.1.0-dev.3 | 209 | 4/17/2021 |
9.1.0-dev.2 | 172 | 4/12/2021 |
9.1.0-dev.1 | 192 | 4/9/2021 |
9.0.5 | 3,037 | 3/31/2021 |
9.0.4 | 3,054 | 3/23/2021 |
9.0.3 | 3,100 | 3/20/2021 |
9.0.1 | 3,078 | 3/18/2021 |
9.0.0 | 3,140 | 3/17/2021 |
9.0.0-dev.4 | 191 | 3/4/2021 |
9.0.0-dev.3 | 200 | 3/1/2021 |
9.0.0-dev.2 | 221 | 2/22/2021 |
8.4.0 | 3,892 | 11/11/2020 |
8.3.0 | 3,180 | 10/28/2020 |
8.2.0 | 3,293 | 10/16/2020 |
8.1.0 | 3,691 | 9/23/2020 |
8.0.0 | 5,302 | 7/1/2020 |
8.0.0-dev.44 | 294 | 6/25/2020 |
8.0.0-dev.43 | 281 | 6/23/2020 |
8.0.0-dev.42 | 328 | 6/22/2020 |
8.0.0-dev.41 | 323 | 6/18/2020 |
8.0.0-dev.40 | 274 | 6/18/2020 |
8.0.0-dev.39 | 293 | 6/15/2020 |
8.0.0-dev.38 | 402 | 6/14/2020 |
8.0.0-dev.37 | 255 | 6/13/2020 |
8.0.0-dev.36 | 311 | 6/13/2020 |
8.0.0-dev.35 | 251 | 6/12/2020 |
8.0.0-dev.34 | 303 | 6/12/2020 |
8.0.0-dev.33 | 351 | 6/10/2020 |
8.0.0-dev.32 | 271 | 6/1/2020 |
8.0.0-dev.31 | 305 | 6/1/2020 |
8.0.0-dev.30 | 360 | 5/30/2020 |
8.0.0-dev.28 | 302 | 5/28/2020 |
8.0.0-dev.27 | 280 | 5/15/2020 |
8.0.0-dev.26 | 271 | 5/14/2020 |
8.0.0-dev.25 | 286 | 5/14/2020 |
8.0.0-dev.24 | 277 | 5/13/2020 |
8.0.0-dev.23 | 277 | 5/13/2020 |
8.0.0-dev.22 | 278 | 5/13/2020 |
8.0.0-dev.21 | 280 | 5/12/2020 |
8.0.0-dev.20 | 283 | 5/12/2020 |
8.0.0-dev.19 | 286 | 5/7/2020 |
8.0.0-dev.18 | 275 | 5/7/2020 |
8.0.0-dev.17 | 285 | 5/6/2020 |
8.0.0-dev.16 | 283 | 5/6/2020 |
8.0.0-dev.15 | 279 | 5/5/2020 |
8.0.0-dev.14 | 276 | 5/5/2020 |
8.0.0-dev.13 | 304 | 5/4/2020 |
7.6.0-dev.13 | 299 | 5/1/2020 |
7.6.0-dev.12 | 304 | 4/30/2020 |
7.6.0-dev.11 | 287 | 4/28/2020 |
7.6.0-dev.10 | 271 | 4/27/2020 |
7.6.0-dev.9 | 280 | 4/24/2020 |
7.6.0-dev.8 | 271 | 4/22/2020 |
7.6.0-dev.7 | 271 | 4/15/2020 |
7.6.0-dev.6 | 267 | 4/15/2020 |
7.6.0-dev.5 | 259 | 4/15/2020 |
7.6.0-dev.4 | 257 | 4/11/2020 |
7.6.0-dev.3 | 268 | 4/10/2020 |
7.6.0-dev.2 | 264 | 4/10/2020 |
7.6.0-dev.1 | 361 | 4/8/2020 |
7.5.2 | 4,742 | 3/20/2020 |
7.5.1 | 3,021 | 3/12/2020 |
7.5.0 | 5,369 | 3/10/2020 |
7.5.0-dev.18 | 293 | 3/5/2020 |
7.5.0-dev.17 | 297 | 3/5/2020 |
7.5.0-dev.16 | 326 | 3/4/2020 |
7.5.0-dev.15 | 266 | 3/3/2020 |
7.5.0-dev.14 | 279 | 3/3/2020 |
7.5.0-dev.13 | 259 | 2/29/2020 |
7.5.0-dev.12 | 380 | 2/29/2020 |
7.5.0-dev.10 | 270 | 2/25/2020 |
7.5.0-dev.9 | 312 | 2/20/2020 |
7.5.0-dev.8 | 342 | 2/18/2020 |
7.5.0-dev.7 | 277 | 2/18/2020 |
7.5.0-dev.6 | 295 | 2/14/2020 |
7.5.0-dev.5 | 303 | 2/12/2020 |
7.5.0-dev.4 | 272 | 2/11/2020 |
7.5.0-dev.3 | 255 | 2/11/2020 |
7.5.0-dev.2 | 400 | 2/8/2020 |
7.5.0-dev.1 | 287 | 2/7/2020 |
7.4.2 | 3,559 | 2/5/2020 |
7.4.1 | 4,150 | 2/3/2020 |
7.4.0 | 4,242 | 1/31/2020 |
7.4.0-dev.4 | 347 | 1/31/2020 |
7.4.0-dev.3 | 323 | 1/29/2020 |
7.4.0-dev.2 | 266 | 1/28/2020 |
7.4.0-dev.1 | 268 | 1/23/2020 |
7.3.1 | 3,454 | 1/21/2020 |
7.3.1-preview.7 | 288 | 1/21/2020 |
7.3.1-preview.1 | 310 | 1/20/2020 |
7.3.0 | 3,410 | 1/19/2020 |
7.2.6 | 3,525 | 1/18/2020 |
7.2.5 | 3,580 | 12/19/2019 |
7.2.4 | 3,632 | 12/19/2019 |
7.2.3 | 3,515 | 12/16/2019 |
7.2.2 | 3,513 | 12/9/2019 |
7.2.1 | 3,549 | 12/4/2019 |
7.2.0 | 3,514 | 11/26/2019 |
7.2.0-preview.10 | 271 | 11/20/2019 |
7.2.0-preview.9 | 266 | 11/19/2019 |
7.2.0-preview.8 | 285 | 11/18/2019 |
7.2.0-preview.6 | 281 | 11/14/2019 |
7.2.0-preview.5 | 285 | 11/14/2019 |
7.2.0-preview.4 | 269 | 11/14/2019 |
7.2.0-preview.2 | 276 | 11/11/2019 |
7.2.0-preview.1 | 273 | 11/9/2019 |
7.1.0 | 3,440 | 11/6/2019 |
7.1.0-preview.8 | 289 | 11/5/2019 |
7.1.0-preview.7 | 284 | 11/4/2019 |
7.1.0-preview.6 | 294 | 11/1/2019 |
7.1.0-preview.5 | 303 | 10/31/2019 |
7.1.0-preview.4 | 304 | 10/30/2019 |
7.1.0-preview.3 | 294 | 10/26/2019 |
7.1.0-preview.2 | 286 | 10/25/2019 |
7.1.0-preview.1 | 279 | 10/24/2019 |
7.0.0 | 3,516 | 10/16/2019 |
7.0.0-rc.41 | 297 | 10/15/2019 |
7.0.0-rc.40 | 307 | 10/15/2019 |
7.0.0-rc.39 | 294 | 10/12/2019 |
7.0.0-rc.38 | 289 | 10/11/2019 |
7.0.0-rc.37 | 288 | 10/10/2019 |
7.0.0-rc.36 | 284 | 10/9/2019 |
7.0.0-rc.35 | 287 | 10/8/2019 |
7.0.0-rc.34 | 283 | 10/8/2019 |
7.0.0-rc.33 | 287 | 10/7/2019 |
7.0.0-rc.32 | 284 | 10/5/2019 |
7.0.0-rc.31 | 294 | 10/3/2019 |
7.0.0-rc.30 | 294 | 10/1/2019 |
7.0.0-rc.28 | 292 | 10/1/2019 |
7.0.0-rc.27 | 287 | 9/30/2019 |
7.0.0-rc.26 | 286 | 9/30/2019 |
7.0.0-rc.25 | 299 | 9/27/2019 |
7.0.0-rc.24 | 282 | 9/27/2019 |
7.0.0-rc.23 | 288 | 9/26/2019 |
7.0.0-rc.22 | 291 | 9/25/2019 |
7.0.0-rc.21 | 283 | 9/24/2019 |
7.0.0-rc.20 | 283 | 9/23/2019 |
7.0.0-rc.19 | 278 | 9/20/2019 |
7.0.0-rc.18.1 | 287 | 9/20/2019 |
7.0.0-rc.18 | 285 | 9/20/2019 |
6.5.0-rc.17 | 298 | 9/19/2019 |
6.5.0-rc.16 | 305 | 9/18/2019 |
6.5.0-rc.15 | 310 | 9/18/2019 |
6.5.0-rc.14.1 | 293 | 9/18/2019 |
6.5.0-rc.14 | 314 | 9/17/2019 |
6.5.0-rc.13 | 292 | 9/16/2019 |
6.5.0-rc.12.2 | 299 | 9/13/2019 |
6.5.0-rc.12.1 | 293 | 9/12/2019 |
6.5.0-rc.12 | 306 | 9/12/2019 |
6.5.0-rc.11 | 307 | 9/11/2019 |
6.5.0-rc.10 | 296 | 9/10/2019 |
6.5.0-rc.9 | 298 | 9/9/2019 |
6.5.0-rc.8 | 282 | 9/6/2019 |
6.5.0-rc.7 | 298 | 9/6/2019 |
6.5.0-rc.6 | 301 | 9/6/2019 |
6.5.0-rc.5 | 292 | 9/2/2019 |
6.5.0-rc.4 | 300 | 9/2/2019 |
6.5.0-rc.3 | 295 | 8/30/2019 |
6.5.0-rc.2 | 310 | 8/29/2019 |
6.5.0-rc.1 | 304 | 8/28/2019 |
6.5.0-beta.5 | 315 | 8/28/2019 |
6.5.0-beta.4 | 321 | 8/27/2019 |
6.0.0 | 3,278 | 8/6/2019 |
6.0.0-rc.7 | 303 | 7/19/2019 |
6.0.0-rc.6 | 299 | 6/28/2019 |
6.0.0-rc.5 | 293 | 6/28/2019 |
6.0.0-rc.4 | 286 | 6/25/2019 |
6.0.0-rc.3 | 302 | 6/20/2019 |
6.0.0-rc.2 | 308 | 5/29/2019 |
6.0.0-rc.1 | 306 | 5/28/2019 |
6.0.0-beta.3 | 308 | 4/17/2019 |
5.3.0-beta.2 | 312 | 3/21/2019 |
5.3.0-beta.1 | 300 | 3/20/2019 |
5.2.0 | 2,881 | 3/19/2019 |
5.1.0 | 3,182 | 1/25/2019 |
5.0.0 | 3,220 | 12/21/2018 |
5.0.0-rc11 | 2,329 | 12/14/2018 |
5.0.0-rc10 | 2,262 | 11/16/2018 |
5.0.0-rc09 | 2,233 | 11/1/2018 |
5.0.0-rc08 | 2,250 | 10/31/2018 |
5.0.0-rc07 | 2,254 | 10/31/2018 |
5.0.0-rc06 | 2,123 | 10/30/2018 |
5.0.0-rc05 | 2,138 | 10/29/2018 |
5.0.0-rc04 | 2,140 | 10/29/2018 |
5.0.0-rc03 | 2,195 | 10/26/2018 |
5.0.0-rc02 | 2,106 | 10/25/2018 |
5.0.0-rc01 | 2,183 | 10/12/2018 |
5.0.0-beta03 | 2,259 | 9/21/2018 |
5.0.0-beta02 | 2,256 | 9/10/2018 |
5.0.0-beta01 | 2,200 | 9/7/2018 |
4.5.1 | 1,984 | 8/7/2018 |
4.5.0 | 4,612 | 8/7/2018 |
4.5.0-rc01 | 2,077 | 6/7/2018 |
4.5.0-beta09 | 2,116 | 6/7/2018 |
4.5.0-beta08 | 2,152 | 5/16/2018 |
4.5.0-beta07 | 2,036 | 5/9/2018 |
4.5.0-beta06 | 2,076 | 4/25/2018 |
4.5.0-beta05 | 2,116 | 4/12/2018 |
4.5.0-beta03 | 2,086 | 4/12/2018 |
4.2.0-beta02 | 2,100 | 3/27/2018 |
4.2.0-beta01 | 2,049 | 2/14/2018 |
4.1.1 | 2,117 | 2/1/2018 |
4.1.0 | 3,399 | 1/15/2018 |
4.1.0-rc10 | 2,105 | 12/19/2017 |
4.1.0-rc09 | 2,199 | 12/19/2017 |
4.1.0-rc08 | 2,164 | 12/12/2017 |
4.1.0-rc07 | 1,973 | 12/5/2017 |
4.1.0-rc06 | 2,036 | 12/5/2017 |
4.1.0-rc05 | 2,021 | 12/5/2017 |
4.1.0-rc03 | 2,086 | 12/4/2017 |
4.1.0-rc02 | 2,053 | 12/4/2017 |
4.1.0-rc01 | 1,944 | 12/4/2017 |
4.1.0-beta09 | 2,030 | 12/3/2017 |
4.1.0-beta08 | 2,053 | 11/25/2017 |
4.1.0-beta07 | 2,009 | 11/23/2017 |
4.1.0-beta06 | 2,021 | 11/22/2017 |
4.1.0-beta05 | 2,022 | 11/21/2017 |
4.1.0-beta04 | 1,689 | 11/21/2017 |
4.1.0-beta03 | 1,603 | 11/17/2017 |
4.1.0-beta02 | 1,697 | 11/17/2017 |
4.0.1-beta01 | 1,695 | 11/6/2017 |
4.0.0 | 4,171 | 10/23/2017 |
4.0.0-rc05 | 1,958 | 10/17/2017 |
4.0.0-rc04 | 2,043 | 10/17/2017 |
4.0.0-rc03 | 1,999 | 10/12/2017 |
4.0.0-rc02 | 2,055 | 10/10/2017 |
4.0.0-rc01 | 2,001 | 10/6/2017 |
4.0.0-beta9 | 2,002 | 10/5/2017 |
4.0.0-beta8 | 1,995 | 10/5/2017 |
4.0.0-beta7 | 2,003 | 10/3/2017 |
4.0.0-beta6 | 1,992 | 9/30/2017 |
4.0.0-beta5 | 2,025 | 9/28/2017 |
4.0.0-beta4 | 2,075 | 9/27/2017 |
4.0.0-beta3 | 2,052 | 9/26/2017 |
4.0.0-beta2 | 2,020 | 9/25/2017 |
4.0.0-beta1 | 1,958 | 9/22/2017 |
3.11.0 | 2,811 | 8/18/2017 |
3.10.1 | 1,967 | 8/18/2017 |
3.10.0 | 3,569 | 8/1/2017 |
3.9.1 | 2,029 | 6/23/2017 |
3.9.0 | 3,430 | 6/13/2017 |
3.8.3 | 2,074 | 5/29/2017 |
3.8.2 | 2,008 | 5/29/2017 |
3.8.1 | 2,586 | 5/26/2017 |
3.8.0 | 2,582 | 5/26/2017 |
3.7.0 | 2,577 | 5/23/2017 |
3.6.1 | 2,083 | 5/19/2017 |
3.6.0 | 2,885 | 5/18/2017 |
3.5.0 | 2,943 | 5/15/2017 |
3.4.0 | 2,666 | 5/4/2017 |
3.3.6 | 2,005 | 4/13/2017 |
3.3.5 | 1,927 | 4/12/2017 |
3.3.1 | 2,018 | 4/12/2017 |
3.3.0 | 4,082 | 4/12/2017 |
3.3.0-preview1 | 1,767 | 4/6/2017 |
3.2.0 | 2,804 | 3/27/2017 |
3.1.0 | 2,471 | 3/22/2017 |
3.1.0-preview4 | 1,996 | 3/9/2017 |
3.1.0-preview3 | 1,713 | 12/9/2016 |
3.1.0-preview2 | 1,880 | 12/9/2016 |
3.1.0-preview1-rc2 | 1,853 | 10/31/2016 |
3.1.0-preview1 | 1,817 | 10/28/2016 |
3.0.9 | 2,072 | 10/19/2016 |
3.0.8 | 2,020 | 8/19/2016 |
3.0.7 | 2,196 | 7/12/2016 |
3.0.7-pre1 | 1,807 | 5/18/2016 |
3.0.0-rc6 | 1,779 | 3/29/2016 |
3.0.0-rc5 | 1,789 | 3/24/2016 |
3.0.0-rc4 | 1,880 | 3/21/2016 |
3.0.0-rc3 | 2,198 | 12/22/2015 |
Please check https://github.com/kephas-software/kephas/releases for the change log.
Also check the documentation and the samples from https://github.com/kephas-software/kephas/wiki and https://github.com/kephas-software/kephas/tree/master/Samples.