Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

ImproveMigrationAttribute#1966

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
mafoo-ASC wants to merge1 commit intofluentmigrator:main
base:main
Choose a base branch
Loading
fromAscenity-UK:main

Conversation

@mafoo-ASC
Copy link

Add VersionAsString toMigrationAttribute so customMigrationAttributes can display a decoded version of their numbering rule updateMigrationInfo to also support new Property

Add VersionAsString to `MigrationAttribute` so customMigrationAttributes can display a decoded version of their numbering ruleupdate `MigrationInfo` to also support new Property
@jzabroskijzabroski self-requested a reviewFebruary 24, 2025 13:29
@jzabroski
Copy link
Collaborator

Hello,
This is a pretty significant breaking change (c.f. GetName() returning a different value), so I likely won't accept it. However,if you could tell me some user stories where this feature could be used, I might be able to suggest an approach that does not break all existing users experiences.

In terms of a decoded version of the numbering rule,can you just use a view (example below)?

What we do on our team is:

yyyyMMdd{##} where{##} is a number from 01 to 99.

Therefore, a database view can be constructed as follows (dialect is T-SQL for Microsoft SQL Server, and so theTRY_CONVERT scalar function may not exist on your platform and your default schema may not bedbo):

SELECT  Version,  TRY_CONVERT(DATE, LEFT(Version,8),112/* yyyyMMdd*/)AS VersionDate,  CAST(RIGHT(Version,2)ASINT)AS SequenceNumberFROMdbo.VersionInfo

@mafoo-ASC
Copy link
Author

As version only stores a long that makes only 8 bytes of available data. We wanted to pack aVersion object into that space so we came up with the below (allowing up to a 16-bit unsigned int in each part). Looking at the Fluent codebase i could only seeGetName being referenced for the purposes of display as when storing to the database it stores the direct long value. I was trying to aim for minimum code changes to achieve this without needing to update the Version object to store more data.

usingFluentMigrator;publicclassVersionMigrationAttribute:MigrationAttribute{/// <summary>///     Represents the version information related to this Migration/// </summary>/// <param name="major"></param>/// <param name="minor"></param>/// <param name="revision"></param>/// <param name="order">Order for match to apply (must be unique across previous information</param>/// <param name="description">///     <inheritdoc cref="MigrationAttribute.Description" />/// </param>publicVersionMigrationAttribute(ushortmajor,ushortminor,ushortrevision,ushortorder,string?description=null):base(VersionMigrationAttribute.FormatRevision(major,minor,revision,order),description){this.AsVersion=newVersion(major,minor,revision);this.Order=order;}[Obsolete("We only want to use a fixed format")]publicVersionMigrationAttribute(longversion,stringdescription):base(version,description){thrownewNotSupportedException("Only use the full format constructors");}[Obsolete("We only want to use a fixed format")]publicVersionMigrationAttribute(longversion,TransactionBehaviortransactionBehavior=TransactionBehavior.Default,string?description=null):base(version,transactionBehavior,description){thrownewNotSupportedException("Only use the full format constructors");}publicVersionMigrationAttribute(ushortmajor,ushortminor,ushortrevision,ushortorder,TransactionBehaviortransactionBehavior,string?description=null):base(VersionMigrationAttribute.FormatRevision(major,minor,revision,order),transactionBehavior,description){this.AsVersion=newVersion(major,minor,revision);this.Order=order;}publicVersionAsVersion{get;init;}publicushortOrder{get;init;}/// <summary>///     Convert supplied <paramref name="version" /> to human-readable version/// </summary>/// <param name="version"></param>/// <param name="asVersion"></param>/// <param name="order"></param>publicstaticvoidExtractData(longversion,outVersionasVersion,outushortorder){varbytes=(Span<byte>)BitConverter.GetBytes(version);asVersion=newVersion(BitConverter.ToUInt16(bytes[7..8]),BitConverter.ToUInt16(bytes[5..6]),BitConverter.ToUInt16(bytes[3..4]));order=BitConverter.ToUInt16(bytes[1..2]);}publicstringVersionToString()=>VersionMigrationAttribute.Format(this.AsVersion,this.Order);privatestaticstringFormat(Versionversion,ushortorder)=>$"Version:{version}, Order:{order}";/// <summary>///     Pack provided version information into required format/// </summary>/// >/// <param name="major"></param>/// <param name="minor"></param>/// <param name="revision"></param>/// <param name="order"></param>/// <exception cref="ArgumentOutOfRangeException"></exception>privatestaticlongFormatRevision(ushortmajor,ushortminor,ushortrevision,ushortorder){try{_=newVersion(major,minor,revision);}catch(Exceptionex){thrownewArgumentOutOfRangeException($"Could not parse version provided by{nameof(major)}/{nameof(minor)}/{nameof(revision)}",ex);}using(vars=newMemoryStream())using(varw=newBinaryWriter(s)){w.Write(order);w.Write(revision);w.Write(minor);w.Write(major);returnBitConverter.ToInt64(s.ToArray());}}}

@jzabroski
Copy link
Collaborator

Thank you, the fact long only stores 8 bytes is a good argument to potentially extend to support a double long.

We wanted to pack aVersion object into that space so we came up with the below (allowing up to a 16-bit unsigned int in each part).

When you sayVersion object, it sounds like you want part of your Version to correspond to a.NET Assembly Version. Can you confirm I understood this correctly?

Completely separately from whether I understood your ask:
Just wondering, if you use git as your version control system, would you prefer having a new (optional) "extended field" that contains a git commit hash id? The way I do build versioning is I follow semver, and so I generate something like "0.0.68+e3d07fc91867a7d77edcd9d167308de341df20e8". The "e3d07fc91867a7d77edcd9d167308de341df20e8" git commit hash would go in a separate column. The advantage to this versus an Assembly Version is that you couldgit checkout e3d07fc91867a7d77edcd9d167308de341df20e8. Then the real feature request is to be able to read-in static data from some injectable context.

@mafoo-ASC
Copy link
Author

Yes we are planning to use an assembly Version to represent the release that we are working on specifically we are targetingSystem.Version and including a order field on the end so the patches can both be unique (as that is required) and ordered.
If you are considering expanding the scope of the version data stored in fluent, double long is going to run into issues as CSharp caps out at long 64bit without moving into byte[] or span is it worth considering moving towards multi fields with legacy support. i.e. [uint, uint, long(legacy field), ushort order) this would give the ability for more flexible formats for users such as [major, minor, patch, order] or [null, date, time, order] and taking this approach will mean if a user wants to transition to the new format on an existing database it will correctly sort the migration still.

Regarding commit id, storing optional data would be really handy, can i suggest string?/nvarchar(max) as this would leave users free to store what they wish (including json)

@jzabroski
Copy link
Collaborator

CSharp caps out at long 64bit without moving into byte[] or span

C# supportsUInt128, andUIntPtr (nuint). byte[] and Span are not hard requirements, although interesting approaches to consider.

I would propose we make MigrationAttribute have a generic abstract base class where the generic argument is an IBinaryInteger. Per the documentation, this would allow you to haveMigrationAttribute<UInt128> or<MigrationAttribute<UIntPtr>. I do not currently want to supportSystem.Version in the core, though, as I think there are very few developers who would follow this pattern, although I am open to exploring why you think it would be a standard idiom for the library to adopt.

Once there is an ABC for MigrationAttribute, the existing MigrationAttribute everyone uses can just be implemented as a closed generic type in terms ofwhere T : long.

This to me seems a lot cleaner and while it would be an ABI breaking change, and some uses of Reflection might break, the core API would not break any C# syntax or require odd customizations from end-users who don't want this complexity.

Thoughts?

@mafoo-ASC
Copy link
Author

Fair point on theuint128, i had forgotten about them as they arestructs rather than Integral types.

Yes moving to an abstract type would certainly help as it allows an individual to choose more storage if they want to without breaking exiting users.

Regarding commit id, storing optional data would be really handy, can i suggest string?/nvarchar(max) as this would leave users free to store what they wish (including json)
This would be a useful add in addition to the 'configurable' Type

As to theVersionToString the way i coded the update means existing users would see no difference as you currently effectively call ToString() on the Version anyway, and it is only where it is displayed in the output (not written to the database). It just allows a CustomeAttribute to choose to display it differently

With supporting System.Version we we develop a lot of projects following the Sprint principle so we are aiming to get the work done within a specific sprint with each sprint being assigned a Version e.g. 1.2.x we can then recognise the source of the patch to the sprint it was related too.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@jzabroskijzabroskiAwaiting requested review from jzabroskijzabroski is a code owner

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

2 participants

@mafoo-ASC@jzabroski

[8]ページ先頭

©2009-2025 Movatter.jp