Giter VIP home page Giter VIP logo

autohistory's People

Contributors

darkxoro avatar ericgreenmix avatar fredikats avatar marcelpotirnac avatar mo-esmp avatar mvarblow avatar paksys avatar qsdfplkj avatar rigofunc avatar threax avatar thumnet avatar whoiskevinrich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

autohistory's Issues

Concurrency Exception when using pack v6.0.0 in Nuget

Ef Core shows the AutoHistory require to have 'rowId' not follow the updated entity's Id, but the 'last_insert_rowid()', what does it mean?

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1ms) [Parameters=[@p0='?' (Size = 56), @p1='?' (DbType = DateTime), @p2='?' (DbType = Int32), @p3='?' (Size = 1), @p4='?' (Size = 11)], CommandType='Text', CommandTimeout='30']
      INSERT INTO "AutoHistory" ("Changed", "Created", "Kind", "RowId", "TableName")
      VALUES (@p0, @p1, @p2, @p3, @p4);
      SELECT "Id"
      FROM "AutoHistory"
      WHERE changes() = 1 AND "rowid" = last_insert_rowid();

The result is that, 'RowId' was forced to be the same as 'Id' in AutoHistory. Or it will throw Concurrency Exception.
So the AutoHistory looks like this, all records happened to have same 'Id' and 'RowId' will insert with success, others fail with exception.

Id RowId TableName Changed Kind Created
1 1 GenericUser {"before":{"Function":null},"after":{"Function":"LPL"}} 3 2022-12-21 06:29:54.4720725
2 2 GenericUser {"before":{"Function":null},"after":{"Function":"LPL"}} 3 2022-12-21 12:42:43.4858065
3 3 GenericUser {"before":{"Function":null},"after":{"Function":"ICX"}} 3 2022-12-22 01:48:10.653962
4 4 GenericUser {"before":{"Function":null},"after":{"Function":"Battery"}} 3 2022-12-22 01:51:59.7880273
5 5 GenericUser {"before":{"Function":"Ext"},"after":{"Function":"LPL"}} 3 2022-12-22 01:52:59.1114256

Wondering that if the 'PrimaryKey' produced the 'RowId' with certain restrictions?

private static string PrimaryKey(this EntityEntry entry)
        {
            var key = entry.Metadata.FindPrimaryKey();

            var values = new List<object>();
            foreach (var property in key.Properties)
            {
                var value = entry.Property(property.Name).CurrentValue;
                if (value != null)
                {
                    values.Add(value);
                }
            }

            return string.Join(",", values);
        }

Turkish character problem

Turkish-specific expressions are not saved in the changed data line. There will probably be problems in other languages ​​as well.
e.g; ö,ü,ş,ı etc.

image

Can't record in Context.Add

When new a entity, I Use DbSet().Add(entity) Then context.Savechanges(); It can't record in autohistory table. But update or delete operation works well! My Microsoft.EntityFrameworkCore.AutoHistory version is 3.1.1. Looking forward to your suggestions

Custom Autohistory

I have updated my project to .Net core 3.0.

Following the article, I did the below in my MVC web application project

class CustomAutoHistory : AutoHistory
{
    public int UserId { get; set; }
}

Then register it in the db context like follows:
modelBuilder.EnableAutoHistory<CustomAutoHistory>(o => { });

Then in my MVC controller code I did below

  if (ModelState.IsValid)
            {
                try
                {
                    _context.EnsureAutoHistory(() => new CustomAutoHistory()
                    {
                        UserId = Convert.ToInt16( User.FindFirstValue(ClaimTypes.NameIdentifier))
                     });
                    _context.Update(cust);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!ClientExists(cust.Id))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
            }

CustomAutoHistory table script

CREATE TABLE [dbo].[|CustomAutoHistory](
[Id] [int] IDENTITY(1,1) NOT NULL,
[RowId] nvarchar NOT NULL,
[TableName] nvarchar NOT NULL,
[Changed] nvarchar NULL,
[Kind] [int] NOT NULL,
[Created] datetime2 NOT NULL,
[UserId] [int] NULL,
CONSTRAINT [PK_CustomAutoHistory] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

The customer records gets updated but there is no record in the Custom History table. Can you please check the custom AutoHistory?

Question: How do I access the history entries

Moin :)

I do have the question on how I do access the history entries? Are there methods available on the object, like:

Person person = _context.person.Find(1);
person.History()

Or are there other ways to access the history entries for a database row?

Thanks :)

Query against AutoHistories with combining actual tables

I would like to use AutoHistory in my project where I need to query some history data with joining current data. Let's say I have an Order table

public class Order
{
    public int Id { get; set; }
    public OrderState OrderState { get; set; }
    public int ProductId { get; set; }
    public int UserId { get; set; }

    public DateTime CreatedOn { get; set; }
    public DateTime ModifiedOn { get; set; }
}
public enum OrderState
{
    Set=1,
    OnTheWay=2,
    Canceled=3
}

And I have an order record that is OnTheWay state. How can I query that what was the ModifiedOn column value before the state changed to OnTheWay from Set. This is just a simple case, we may have a lots of conditions depends on other columns, do you think it is costly to make use of this AutoHistory table like that?

Problem with combined pk

If you use a combined pk then there is an issue that you can not delete those rows. you can create it and they will be no record in history table. But a remove returns in an error. Tested with mssql.

Invalid object name 'AutoHistory'

Hi. I'm having trouble getting this started in my project. My project could save prior to adding AutoHistory. Now I get the below exception on any save. There still is no table named AutoHistory in the database.
Microsoft.EntityFrameworkCore 5.0.15
Microsoft.EntityFrameworkCore.AutoHistory 5.0.8

Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid object name 'AutoHistory'.
at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction)
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at Microsoft.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
at Microsoft.Data.SqlClient.SqlDataReader.get_MetaData()
at Microsoft.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean isAsync, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
at Microsoft.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String method) at Microsoft.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior) at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject) at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection) ClientConnectionId:ed0320bd-4a8f-40a6-9f46-2d7f56cab67b Error Number:208,State:1,Class:16 --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable1 commandBatches, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList1 entries) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList1 entriesToSave)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(DbContext _, Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func3 operation, Func3 verifySucceeded)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at myDC.SaveChangesAsync(CancellationToken cancellationToken)

AutoHistory is not working with PostgreSQL

Hi,

The AutoHistory table is created in the database but there are no records.

My config is:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // enable auto history functionality, 22023 is max limit supported by PostgreSQL
    modelBuilder.EnableAutoHistory(22023);
}

and during any save or update I am using the following:

await UnitOfWork.SaveChangesAsync(true);

Further technical details

EF Core version: 2.0.1
Database Provider: Npgsql.EntityFrameworkCore.PostgreSQL
Operating system: Windows 10
IDE: Visual Studio Enterprise 2017 15.4.5

Created date problem

It is more correct DateTime.Now than DateTime.UtcNow for Created property in the AutoHistory class. Because utcnow does not change.

Recording added entities does not work

I tried to enable recording of added entities as described in the README. Unfortunately it's not working.
In the code of AutoHistory there is an extension method called AddedHistory which seems to do the trick but this method is not called at all in the class DbContextExtensions

EF Core version: 5.0.11
AutoHistory version: 5.0.8

Introduced by https://github.com/Arch/AutoHistory/pull/61/files

insertion history

When are you planning to add feature of insertion history, as currently it supports only updation and deletions

Does AutoHistory track histories for related entities?

I have a root object that has a number of child entities being created and modified from the root object.
Auto history seems to track only the changes from base entity. is there a way to track the child entities automatically?

Is this working?

I have install this nuget packet in my sample project. But this don't create any historie data in my database.
Here my implementation:

DbContext:

public class BlogDataDbContext: DbContext
{
        public BlogDataDbContext(DbContextOptions<BlogDataDbContext> options): base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.EnableAutoHistory(null);
        }

        

        public DbSet<Blog> Blogs { get; set; }
}

Somemethod of saving:

 public class EditModel : PageModel
    {
        private readonly BlogDataDbContext _context;

        public EditModel(BlogDataDbContext context)
        {
            _context = context;
            _context.EnsureAutoHistory();
        }

        [BindProperty]
        public Data.BlogData.Blog Blog { get; set; }

        public async Task<IActionResult> OnGetAsync(Guid? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            Blog = await _context.Blogs.SingleOrDefaultAsync(m => m.BlogId == id);

            if (Blog == null)
            {
                return NotFound();
            }
            return Page();
        }

        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            _context.Attach(Blog).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!BlogExists(Blog.BlogId))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return RedirectToPage("./Index");
        }

        private bool BlogExists(Guid id)
        {
            return _context.Blogs.Any(e => e.BlogId == id);
        }
    }

After the change of an element no new entry in the AutoHistorie table. This is strange...

Change Type of PK

The PK column in the history table is currently set to be an int with no straight forward method for providing an alternate type. In large scale systems this presents a hard cap on the number of history entries that can be created at a bit more than 2 billion. This is a large but not outrageously large value given that the table will log all changes written to the database. In addition most databases value uniqueness and speed over density when assigning int pk values so the actual number of records written can be significantly lower than ~2 billion. In practive in some of our high usage systems we are having to roll the audit table every couple of months.

We working on a work around that adds a value converter to the id property to "convert" the int ud to Guid.NewGuid(). This works to some degree but means we need to define a seperate model class to treat the audit log as a view if we want to retieve any data from it.

I think changing the type outright would probably present a major breaking problem for a number of applications but I think providing an option to inherit from a generic type would allow those that need it to define their own PK.

History, Before And After Json Looks Same

Hi

I am getting Auto History Result is as follows.

{
"before": {
"Addr1": "string",
"Addr2": "string",
"CntPerson": "string",
"CntPersonPhone": "string",
"CreatedBy": "Easwar",
"CreatedDate": "2018-01-27T13:50:37.2754446",
"EMail": "string",
"GstNumber": "string",
"IndiaState": "string",
"IsActive": true,
"MfrName": "Abott International",
"MfrShortName": "string",
"PanNumber": "string",
"Phone": "string",
"PinCode": "string",
"Place": "string",
"TinNumber": "string",
"TransactionTime": "0001-01-01T00:00:00",
"UpdatedBy": "Easwar",
"UpdatedDate": "2018-01-27T13:50:37.2754446"
},
"after": {
"Addr1": "string",
"Addr2": "string",
"CntPerson": "string",
"CntPersonPhone": "string",
"CreatedBy": "Easwar",
"CreatedDate": "2018-01-27T13:50:37.2754446",
"EMail": "string",
"GstNumber": "string",
"IndiaState": "string",
"IsActive": true,
"MfrName": "Abott International",
"MfrShortName": "string",
"PanNumber": "string",
"Phone": "string",
"PinCode": "string",
"Place": "string",
"TinNumber": "string",
"TransactionTime": "0001-01-01T00:00:00",
"UpdatedBy": "Easwar",
"UpdatedDate": "2018-01-27T13:50:37.2754446"
}
}

It Seems Before and After object are Same. Any Issue?

Enhancement: Needs ExcludeFromHistory property, for fields.

When recording history, there are fields that I don't want their real data recorded in history. These are like Personal Identifying data, or passwords (even after being hashed).

Though making this an extension method that would work in the OnModelCreating call, it would also be nice to see it as an attribute for the model fields themselves.

[ExcludeFromHistory(ReplacementValue="")]

EnsureAutoHistory stopped working after changing to async/await

I am struggling to make AutoHistory work after chaning my controllers to async/await pattern.

I can't tell for sure it's that, but looking through my commits that is the only thing I can identify has changed since the time it worked.
Problem is that now every entry created by the framework is of the Kind Detached and the Changed column is NULL

Has anyone experienced this behaviour?
Thanks & kind regards,
Dino

the data not save nested table

Hi Team,
The value of before and after not save data with nested table, how can I log all data change include (table relationship change)

Thanks

Changed column too short

Hello,

Is there any reason for having the Changed column just 2048 long?

image

Couldn't be replaced by nvarchar(max)?

Table structure

Hi,

I'm using EF Core but I'm not using migrations and context.EnsureAutoHistory() doesn't work; because the table doesn't exist. I want to create the table in SQL, can you tell me what fields does the AutoHistory table have?

Thank you very much in advance.

AutoHistory doesn't work with UnitOfWork

Hi, AutoHistory doesn't work with UnitOfWork if atrribute is nullable.

I rewrited your UnitTest.

    public void Entity_Update_AutoHistory_Test()
    {
        var unitOfWork = new UnitOfWork<BloggingContext>(new BloggingContext());

        var blogRepository = unitOfWork.GetRepository<Blog>();
        var postRepository = unitOfWork.GetRepository<Post>();

        var blog = new Blog()
        {
            BlogId = 1,
            Url = "htttp://www.google.com/"
        };

        var post = new Post()
        {
            PostId = 1,                
            Content = "Text 1",
            Title = "Text 2"
        };

        blogRepository.Insert(blog);
        postRepository.Insert(post);

        unitOfWork.SaveChanges(true);

        post.Age = 1;           

        unitOfWork.SaveChanges(true);
    }

...
public int? Age { get; set; }
...

It throws exception

image

Exception using .net 6

When trying to run it with .net 6 and ef core 6.0.1 this throws an exception during startup.

System.MissingMethodException: Method not found: 'System.Type Microsoft.EntityFrameworkCore.Metadata.ITypeBase.get_ClrType()'.
   at Microsoft.EntityFrameworkCore.DbContextExtensions.AutoHistory[TAutoHistory](EntityEntry entry, Func`1 createHistoryFactory)
   at Microsoft.EntityFrameworkCore.DbContextExtensions.EnsureAutoHistory[TAutoHistory](DbContext context, Func`1 createHistoryFactory)
   at Microsoft.EntityFrameworkCore.DbContextExtensions.EnsureAutoHistory(DbContext context)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.