csf-dev / csf.orm Goto Github PK
View Code? Open in Web Editor NEWTypes used to abstract the usage of an ORM
License: MIT License
Types used to abstract the usage of an ORM
License: MIT License
The ORM part of this library is mainly about creating an abstraction for the use of ORMs (primarily NHibernate) so that I may test logic, whilst detached from the ORM itself.
This ticket is to formally design and document the API of that abstraction.
The current API is missing some useful bits of functionality which I frequently use from NHibernate.
ToLazy<T>()
ToLazyValue<T,V>(Expression<Func<IQueryable<T>,V>>)
EagerlyFetch<P,C>
EagerlyFetchMany<P,C>
ThenEagerlyFetch<P,C,GC>
ThenEagerlyFetchMany<P,C,GC>
These functions must be implemented as extension methods. However, I want their actual implementation logic to be contained within a normal service which may be injected.
I will need to expose a static method which allows me to substitute the implementation which 'drives' these extension methods.
I also need to create some in-memory implementations of these functions, so that they may be provided by no-op logic, for testing purposes.
Abstract base classes should be created for the two pairs of similar functionality:
The base classes will hold the functionality which is identical, the subclasses will then only have the functionality which is unique to them.
The query and persister are reachable from the data connection. The transaction factory should be as well. This means that all of the functionality can be reached just using a connection factory.
This ticket is to investigate, devise and implement an improvement for the way in which identity instances may be compared for equality.
At present, when comparing two instances of IIdentity
for equality, the developer is likely to use the equality operator: ==
. This is problematic because if the compared variables are presently typed using their interfaces (which is encouraged) then reference equality will be used instead of value equality. Because behind the scenes identity objects are structs, reference equalitywill never be true.
It is beneficial to type identities as interfaces. This is in order to support generic covariance. If I were to solve this problem by not using interfaces, I would lose the ability to do the following (assuming Cat is a subclass of Animal):
IIdentity<Cat> catId = GetCatId();
IIdentity<Animal> animalId = catId;
Whilst the variables are typed as interfaces, operator overloads upon the identity type, such as the equality operator, will not be used under any circumstances.
There is some discussion regarding this but I don't see it being implemented any time soon, given that this proposal is already 3 years old.
Given that the core problem is the mutual exclusivity of covariance (interfaces only) and operator overloading (not interfaces), I doubt that there is a simple solution in swapping from structs to classes for the implementations.
In fact, after some investigation, I am already using classes and not structs for identity objects.
As well as being a workaround, this could even be a long-term solution.
Instead of using the equality operator to compare identities, use the static Object.Equals(object, object)
method to compare them.
So, instead of this:
identityA == identityB
Use this:
Equals(identityA, identityB)
This will use the overridden Equals methods on the underlying identity objects which will return the correct result.
NHibernate has upgraded beyond version 4.x. This ticket is to create a version or versions of this library which support all NHibernate versions from 4.0.x to the current latest NHibernate.
Currently, the identity factory requires an identity value to be an exact type match for the desired identity value.
For example, of an entity requires Int64
, then an identity cannot be created using an Int32
, even though it is compatible/has an implicit cast available. This ticket is to relax that restriction so that compatible types may be used.
System.ArgumentException : Identity type `Int64' was specified but provided identity value was a `System.Int32'.
Parameter name: identityValue
at CSF.Entities.IdentityFactory.Create (System.Type entityType, System.Type identityType, System.Object identityValue)
at CSF.Entities.Identity.Create[TEntity] (System.Object identityValue)
It has become apparent that the static Identity
class is not compiled a part of the project.
I'm not entirely sure now as to why this is the case. Is it that I planned to deprecate and remove this functionality, or perhaps it should be compiled and included (and it's a mistake that it's not).
This ticket it to investigate, find out why, and then either delete it altogether or include it in the compiled library. Once that's done a new version should be published.
My main ORM of choice (NHibernate) now supports asynchronous operations (unsure which exactly). This ticket is to design an API which will support the usage of that asynchronous
API.
I plan to support versions of NHibernate back as far as 4.0 with this library. Because of this, I'll have to implement versions of the classes which execute synchronously in order to support NH4.
All libraries in this repo except for tests should be made available via NuGet.
net45
Currently there is no parallel to the session factory or a session.
One must be created so that a domain layer may connect/disconnect without needing NHibernate directly.
The NHibernate libraries provide adapters, allowing NHibernate to be used with the ORM API. I want to support two different major versions of NHibernate though, 4 and 5.
These NHibernate libraries have very slightly different APIs of their own and so, to deal with the differences, I'd like to support them via separate packages.
There's a lot of functionality on the two static classes:
Entity
Identity
This logic should be reviewed and, where possible, moved to new services with interfaces. Things like the equality comparison for identity would be provided by an equality comparer etc.
In the latest SonarCloud report there are a number of Major-severity issues reported. These must all be addressed.
Sonar cube must be set up to measure code quality.
This project currently contains obsolete code and types. To date it hasn't been removed, to preserve backwards-compatibility. It is now time to remove it, especially since we will be releasing new major versions of everything.
There is a potential bug in the way in which entities are compared for equality.
Say we have a base class Animal with two subclasses: Cat and Dog.
Cat ID 5 and Dog ID 5 could both exist in the same application, if the underlying data-store used a 'table per concrete class' relational model for storing entities.
In the above scenario, I think that the entity equality mechanism would consider them to be equal even though they are not.
If the underlying database were using 'table per class' or 'single table' then this would not be an issue, because two entities of different types (in the same class hierarchy) cannot have the same identity.
This must be investigated to determine its impact and, if it is a true bug, a solution devised.
The NHibernate library should mainly be about implementations of the ORM API defined elsewhere in the solution. However, it has picked up a number of unrelated types which are for NHibernate but which aren't for the ORM.
These should be split away into projects of their own, do that they may be used independently of the ORM API.
This ticket is to review those types and split them away where applicable.
Now that five repositories have been merged into one, to create a monorepo, Travis and AppVeyor must be set up once again.
SonarCloud reports a high amount of duplicate code. This is likely caused in large part by the duplication of NHibernate implementations between the v4 and v5 libraries.
Duplicate code should be moved to a shared library and shared between the two implementation-specific ones.
There are some obsolete types in this repo, particularly everything in the specifications namespace. They should all be removed.
Once this is done, a new major version of this library must be released.
When using the persistence tester, if persistence fails and an error result is returned, there can be a crash error when inspecting that result because references may be lazily-loaded outside of the scope of the ISession
used by the test.
The issue here is that during the Assert
stage, in order to display friendly results to the user, the ToString()
method is executed on objects which have not yet been fetched from the DB. This causes a crash during the test instead of showing the actual test results.
A possible solution (unsure whether to go with this or not) would be to get the ToString()
result ahead of time in the persistence tester, when creating the result object. If exceptions occur then catch and swallow them because there's nothing we can do at that point.
Additionally, at the assert stage of the test, if getting an object value causes an exception, simply record the exception and otherwise swallow it. In the summary print something like <[InvalidOperationException] raised reading this value>
, so the user knows which exception was raised, but still sees results.
The interface IGetsTransaction
should provide a mechanism by which to determine if a transaction is already active. This could be a simple boolean property named IsTransactionActive
.
The use-case is that sometimes we want to start a new transaction, but only if one is not already active.
The persistence tester has its own abstractions for the ORM backend. These largely duplicate the standard ORM implementations though, which are already part of this repository.
This ticket is to combine these so that only the ORM implementation libraries are required.
Setting Entity<T>.IdentityValue
should not throw an exception is a compatible object is specified for the new identity value.
Currently, the cast from object
to TIdentity
fails if the entity is Entity<long>
but an Int32
is specified as the value. Despite it being possible to cast Int32
to Int64
implicitly under other circumstances, this cast fails.
If the value is compatible with the identity value type, then it should be gracefully converted. This setter should only throw if the new value cannot be converted.
It seems that the README is out of date and refers to obsolete code. The contents of the file should be reviewed and - where appropriate - updated.
Consider also, moving done of the docs to the wiki if there's enough of it.
I have noticed that I have some functions which are *Async
, but do not return a Task
object. They must, as this is part of the async pattern.
An example can be found in the NH 4.x transaction adapter. This must be fixed.
I am unsure as to why the NHibernate packages depend upon ConfigurationManager or SQLite.
The dependencies for both NH packages should be reviewed and slimmed down if they can be.
This repository is the merger of five old repositories, into a monorepo.
This means that the README document must also mention all five. It should also point to the wiki, where I can add further information.
Currently, the package dependency between the ORM NHibernate packages and the NHibernate library specify only a minimum version. They should also specify a maximum.
This ticket is to rework the implementation of transactions in this library to integrate with the built-in TransactionScope
functionality, as described in this documentation.
This is a standard .NET API which abstracts transaction management away from any specific implementation-related API.
The solution to this ticket must support the following:
ISession
from dependency injection
This should be placed in a new library/project within this solution. It should be a pre-created convention mapping files. These may be applied to any project in order to auto-map everything.
As of the version 2 release, types marked as deprecated in version 1.x may (and should) be removed.
There is currently no test coverage for the NHibernate 5 integration. This needs to be created.
The two CSF.ORM.NHibernateX packages (for NH 4 & 5) cannot be installed. This is because they depend upon the nonexistent CSF.ORM.NHibernate.Common
package. The Common library isn't intended to be a NuGet package, it's another library, bundled inside the NH4 and NH5 packages.
I need to remove the dependency which the dotnet build system has implicitly added from the NHibernate impl projects into the NHibernate common project.
It looks like there's some advice on how to do this in this dotnet/NuGet feature request, particularly the workaround linked from the bottom of the issue description. This might be as simple as using PrivateAssets="all"
in the reference. I have already handled the copying of the build assets over. It's only the unwanted package dependency that is causing me a problem.
This project will likely contain a number of different packages:
These will largely be renamed versions of existing projects.
The first three of these libraries have no direct dependency upon any ORM. They could target a number of frameworks and permit wide support.
The last two, though, have a direct dependency upon NHibernate. I am aware that NHibernate 4.x is only available for .NET Framework 4.x, whereas NHibernate 5.x is built for netstandard.
This might mean that libraries which support NHibernate must be split into separate packages which support different framework stacks depending upon the version of NHibernate which they need to support.
There is some information available which suggests that NuGet package dependencies can be grouped and varied by framework/runtime target.
This way I could say that in .NET Framework 4.5 target, we depend upon only NHibernate 4.x but in netstandard we can accept 5.x and up.
Where possible and practical, I'd like the libraries in this project to support both netstandard 2 and also the .NET Framework 4.5.
That might not be possible for some of the NHibernate libraries, because I don't think that newer versions of NHibernate support framework 4.5.
This also includes ensuring that - where applicable - tests on CI platforms test both netstandard2.0
and net45
builds of the code.
The IEntityData interface mainly duplicates IQuery and IPersister. This is on the borderline of an SRP violation.
Consider changing the entity-related functionality to just a query.
This repository is made from the merger of five others. These other five should now be archived and updated to point here.
These other repositories should be archived so that they no longer accept new commits. They should also be updated with a message pointing here, so that readers can find the new development.
The repository CSF.Data.NHibernate might need to be kept; see issue #16, because I think that some of its contents don't belong in this repo.
To show developers how to use the packages in this repository, a short documentation wiki would be useful.
There has been an issue raised on the NHibernate project, subsequently rejected, which requests support for mocking ISession
and the Linq queries/extension methods.
That's a large part of the purpose of this project. In that comment thread/discussion there are other ideas discussed, along with links to other sources. This all needs evaluating in the context of this project. It could be that there are better solutions available for what I want to do.
Currently, the Theorise
method of the in-memory DataQuery
class crashes with a "recursive lock not allowed" exception if it is used. This must not happen. The root cause is that Theorise
internally calls Get
.
An error in the nuspec files means that their dependencies are incorrect.
Version 3.0.0 of the NHibernate packages should depend upon version 3.0.0 of CSF.ORM but accidentally they use the 2.x version still.
Currently I'm not too sure about the test coverage for the logic in these libraries. Sonar Cube will help a little but I'm particularly concerned about the NHibernate integration.
This needs to be reviewed and checked that everything is tested thoroughly. This includes testing against a real NHibernate environment and also testing that the in-memory implementations offer equivalent functionality.
Back in NUnit 3.6, released in 2017 a new attribute was added to the framework named [NonTestAssembly]
. It is designed to inform test runners that - whilst an assembly references NUnit.Framework - it does not contain tests which should be executed.
This would be useful for CSF.PersistenceTester.NUnit because it is an NUnit extension library which has no tests of its own.
The wiki currently has no information about the persistence tester. Usage information must be added.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.