Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using System;
using PetaPoco.Tests.Integration.Models;
using Shouldly;
using Xunit;
using PetaPoco.Tests.Integration.Providers;

Expand All @@ -11,5 +14,52 @@ public MSAccessInsertTests()
: base(new MSAccessTestProvider())
{
}

/// <summary>
/// Regression test for MS Access DateTime millisecond handling.
/// MS Access OLE DB provider cannot handle DateTime parameters with sub-second precision.
/// Without proper handling in MapParameterValue, DateTime values with milliseconds cause
/// "Data type mismatch in criteria expression" errors. The fix truncates milliseconds before
/// sending DateTime values to the OLE DB provider.
/// See: https://github.com/CollaboratingPlatypus/PetaPoco/issues/736
/// </summary>
[Fact]
public void Insert_GivenPocoWithMillisecondPrecisionDateTime_ShouldInsertSuccessfully()
{
// Test with DateTime that has NO milliseconds (baseline)
var personWithoutMillis = new Person
{
Id = Guid.NewGuid(),
Name = "No Milliseconds Person",
Age = 35,
Height = 180,
Dob = new DateTime(2000, 6, 15, 14, 30, 45, 0, DateTimeKind.Utc)
};

_ = DB.Insert(personWithoutMillis);
var retrieved1 = DB.Single<Person>(personWithoutMillis.Id);
retrieved1.ShouldNotBeNull();
retrieved1.Dob.ShouldNotBeNull();

// Test with DateTime that HAS milliseconds (the actual regression test)
// Before fix: throws OleDbException "Data type mismatch in criteria expression"
// After fix: succeeds but milliseconds are truncated
var personWithMillis = new Person
{
Id = Guid.NewGuid(),
Name = "With Milliseconds Person",
Age = 40,
Height = 185,
Dob = new DateTime(2000, 6, 15, 14, 30, 45, 123, DateTimeKind.Utc)
};

_ = DB.Insert(personWithMillis);

var retrieved2 = DB.Single<Person>(personWithMillis.Id);
retrieved2.ShouldNotBeNull();
retrieved2.Dob.ShouldNotBeNull();
// Allow 1 second tolerance because milliseconds are truncated by the fix
retrieved2.Dob.Value.ShouldBe(personWithMillis.Dob.Value, TimeSpan.FromSeconds(1));
}
}
}
9 changes: 9 additions & 0 deletions PetaPoco/Providers/MSAccessDatabaseProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ public override object MapParameterValue(object value)
return (int)ul;
}

// MS Access OLE DB provider cannot handle DateTime parameters with sub-second precision (milliseconds).
// Truncate to whole seconds to avoid "Data type mismatch in criteria expression" errors.
// See: https://github.com/CollaboratingPlatypus/PetaPoco/issues/736
if (value is DateTime dt)
{
// Remove milliseconds by creating new DateTime with only year/month/day/hour/minute/second
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Kind);
}

// Let base handle other common conversions (eg: bool -> int)
return base.MapParameterValue(value);
}
Expand Down