Saving DateTime to sql without milliseconds - entity-framework

How do I save datetime property in EF without the milliseconds?
I I save it like this:
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "
{0:MM/dd/yyyy}")]
[Column(TypeName = "datetime2")]
public DateTime ProcessingDateTime { get; set; }
I get data with milliseconds?
Any Ideas?
tX
Tally

For those that have encounter this problem, there is a away to solve this problem in a agnostic way agnostic in EF CORE:
1-go to the OnModelCreating
2- add to the property the extension method HasConversion, that will remove the milliseconds from the datetime, in both reads and writes
builder.Entity<Table>().Property(u => u.Date).HasConversion(dt => dt, dt => dt.AddTicks(-dt.Ticks % TimeSpan.TicksPerSecond));

Related

How Do I Format Date in Model or Linq Query for Controller Output

I have an API controller that renders a JSON result which is used by the infinite scroll plugin. Unfortunately, I don't see any way to format the output using the plugin itself, so I have to make sure the output is properly formatted before it is sent to the controller.
I have run into a problem with DateTime because all the examples I can find for formatting it rely on using server side code in the view. That is not an option with infinite scroll.
Preferably this should be done in the LINQ query or the model. I tried changing my model to:
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime? Date
{
get;
set;
}
That did not work. Likewise, changing the part of the select clause of the link query that says Date = p.Date to stuff like Convert.ToDateTime(p.Date).ToString("dddd MMMM dd, yyyy") doesn't work because you can't implicitly convert a string to date or something. That last example is exactly how I do it in the view.
How do I replicate that output in the JSON of an API controller?
NEW: The same seems true with decimals. I have prices that should include two decimals, but the JSON output in the controller only has as many as the user put in. This results in stuff like $20.5 followed by $0 and $22.55. The last of course being correct.
My price model looks like this:
[Required(ErrorMessage = "Price Required!")]
[Range(.00, Double.PositiveInfinity, ErrorMessage = "Must Be Positive Number!")]
[Display(Name = "Price:")]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal? Price { get; set; }
Try this...
public DateTime? Date { get; set; }
public string StringDate
{
set => Date?.ToString("0:MM/dd/yyyy")
}

Fluent NHibernate Readonly property after Insert (Audit - type Data Created Updated Dates)

I HAVE to be overthinking this because it's a super common workflow just not finding the right answer. Using Fluent NHibernate over postgres and given the following simple class and mapping, how can I set the audit data in code, then secure/lock it during subsequent update calls.
public class RecordEntity
{
public virtual int Id {get;set;}
public virtual DateTime CreatedOn {get;set;}
public virtual DateTime UpdatedOn {get;set;}
}
And Mapping
public class RecordEntityMapping:ClassMap<RecordEntity>
{
public RecordEntityMapping()
{
Id(x => x.Id).GeneratedBy.Increment();
Map(x => x.CreatedOn);
Map(x => x.UpdatedOn);
}
}
then I want to be able to do something like this in my repository
...
var record = new RecordEntity();
record.CreatedOn = record.UpdatedOn = DateTime.UtcNow;
await _session.SaveAsync(record); // Created on should be properly persisted.
...
Then an update...
//record passed in from somewhere else...
record.UpdatedOn = DateTime.UtcNow;
await _session.UpdateAsync(record); // CreatedOn here will be who knows what.
...
Ok options.
I could put in a postgres rule that sets a date on insert, then set the property to be generated.insert() and .ReadOnly().
I could set up some kind of interceptor that checks whether I'm doing an update or insert, and react accordingly.
is there a way in nhibernate or postgres that says ignore if default then make sure it's always default on updates.
I know I can always make an extra call to get the data out of the db and merge the records. kind of defeats the purpose.
There's got to be an easier way. What am I missing? What other options do I have?

How/When Sql server updates the record timestamp value, if I have a transaction with multiple CRUD operations

I am working on an asp.net mvc web application and I am using an entity framework to map my tables into model classes.
I have the model class representing VMS:-
public partial class TMSVirtualMachine
{
public int TMSVirtualMachineID { get; set; }
public int ServerID { get; set; }
public int RoleID { get; set; }
public Nullable<int> BackUpStatusID { get; set; }
public Nullable<int> StatusID { get; set; }
public Nullable<int> MonitoreID { get; set; }
public Nullable<decimal> TotalStorage { get; set; }
public string Comment { get; set; }
public byte[] timestamp { get; set; }
public Nullable<long> IT360SiteID { get; set; }
public virtual TMSServer TMSServer { get; set; }
//cde goes hereā€¦
}
And I have the following repository method , which will move all the current server;s VMS to another server, by changing the VM's ServerID as follow:-
public int changeVMsServer(AssignVMsToServer s, string username)
{
int count = 0;
var currentvms = tms.TMSVirtualMachines.Where(a => a.ServerID == s.serverIDForm);
foreach (var v in currentvms)
{
v.ServerID = s.serverIDTo;
tms.Entry(v).State = EntityState.Modified;
count++;
}
SaveChanges();
return count;
}
Currently if two users call the above method at the same time one of them will get a DBUpdateConcurrentException, since the timestamp for a VM when trying to save it, will be different than when the VM was retrieved.
My question is basically how SQL server 2008 r2 manage the timestamp column. Let take the following scenario:-
First user retrieve 5 VMs, then generate 5 SQL update commands and save.
Second user retrieve 5 VMs, then generate 5 SQL update , and when trying to save , EF will detect that the timestamp has been changed for atleast one VM and raise a DBUPdateException.
Now when the first user perform the 5 SQL updates operation , his work will not be saved until the 5 update operation successed , since the 5 update operations are wrapped in a single trancaction.
Q1) So when will sql server 2008 r2 changed the timestamp column for the 5 servers , when the transaction is completed ?, or when a single update operation is saved ?, and if the transaction failed will sql server return the old timestamp value ?
Sorry for the long email, but I tried searching for a clear answer , but could not reach a final conclusion.
MSDN documentation on timestamp is quite clear:
Is a data type that exposes automatically generated, unique binary numbers within a database. timestamp is generally used as a mechanism for version-stamping table rows. The storage size is 8 bytes. The timestamp data type is just an incrementing number and does not preserve a date or a time. To record a date or time, use a datetime data type.
...
You can use the timestamp column of a row to easily determine whether any value in the row has changed since the last time it was read. If any change is made to the row, the timestamp value is updated.
So, it's clear that the timestamp is modified when the row changes.
EF will use this column for concurrency checking: if an app reads a row, modifies it and try to save the changes in the DB and the timestamp changed since it was read, then the concurrency exception is thrown.
As to the transaction, what you're missing is the "transaction isolation" concept. The timestamp column changes when a change is made to the row. But what happens if a different connection tries to read this row depends on the isolation level: the row can be locked until the transaction finishes (so the other connection will have to wait until that moment), or the other connection can read the new uncomitted value or it can read the old value. It depends on the isolation level.
By default in SQL Server the isolation level is:
READ COMMITTED
Specifies that statements cannot read data that has been modified but not committed by other transactions. This prevents dirty reads. Data can be changed by other transactions between individual statements within the current transaction, resulting in nonrepeatable reads or phantom data. This option is the SQL Server default.

how to avoid creating entities for returning small data from database

Oftentimes I need to return a list of two or three columns from a stored proc in the data layer. I usually use entities to push data back to the business/UI layer. However, I don't want to create an entity for something that is not really an entity.
Lets say I have to return a set of "date, string, string", is there any other way to do this.. for two columns, i can perhaps get away with a dictionary. I always end up creating a dummy entity but thought I'll ask this time.
Create a new model to store the data:
public class ResultModel
{
public DateTime DateTime1 { get; set; }
public string String1 { get; set; }
public string String1 { get; set; }
}
then just store your data into this like so:
IEnumerable<ResultModel> results =
Entities.Table.Select(r => new ResultModel
{
DateTime1 = r.DateTime,
String1 = r.String1,
String2 = r.String2
});
Not verified the code but is a guide as to how to achieve this.
You could probably use a Tuple for this kind of data however I've never found any real detriment to creating more understandable types, even for simple data.

Entity Framework and SqlDateTime overflow best practices

System.DateTime can take a wider range of values than SQL Server's DateTime. Hence there is class System.Data.SqlTypes.SqlDateTime which mimics the later.
Consequently I would have expected Entity Framework to choose SqlDateTime, but it didn't.
So my questions are...
What are the best practices to insure that your DateTime values will not cause problems when you try to save them to your database?
Is there any way of forcing EF to use SqlDateTime?
There's a number of things you can do:
if you're using SQL Server 2008 or newer, you can use the DATE or DATETIME2 data types on the database which offer the same date range as .NET's DateTime
if you can't use those new data types, it will be up to you to handle some checking / validation on your date fields before things are being stored into the persistent store. EF EntityObject offers lots of ways to tap into the process of validating and saving objects - pick one approach that works for you
More specifically, try this: http://www.vfstech.com/?p=111
Maybe this is an old thread but I will post my findings on this for the others :
Let say that we have dev env : EF 5, CodeFirst, SqlCE 4.0 :
public abstract class Entity : IEntity, IEquatable<Entity>
{
public virtual int Id { get; protected set; }
public virtual DateTime LastModified { get; set; }
[DataType(DataType.Date)]
public virtual DateTime CreatedOn { get; set; }
[DataType(DataType.DateTime)]
public virtual DateTime CreatedOn2 { get; set; }
[DataType(DataType.Time)]
public virtual DateTime CreatedOn3 { get; set; }
public virtual DateTime CreatedOn4 { get; set; }
}
with such a custom mapping :
public EntityMapping()
{
HasKey(e => e.Id);
Property(e => e.Id);
Property(e => e.LastModified).IsRequired().IsConcurrencyToken();
Property(e => e.CreatedOn).IsRequired();
Property(e => e.CreatedOn2).IsRequired();
Property(e => e.CreatedOn3).IsRequired();
Property(e => e.CreatedOn4).IsRequired();
}
This produces this, which means that we will have the overflow exception.
Changing the mappings to this while still working with SQL CE 4.0 :
Property(e => e.CreatedOn).IsRequired().HasColumnType("datetime2");
Property(e => e.CreatedOn2).IsRequired().HasColumnType("date");
Property(e => e.CreatedOn3).IsRequired().HasColumnType("date");
Property(e => e.CreatedOn4).IsRequired().HasColumnType("datetime2");
Gives this error.
Switching to SQL Server Standart 2012 seems to solve the problem ( That is not a solution for sure - just for the experiment ). The created SQL Server schema is this.
I am not an expert in Sql but it looks like to me that SQL CE does not support these dates. the problem with development env. remains. DateTime can be substituted but can bring a lot of refactoring here and tehere.
Remember also that SqlDateTime and DateTime are very different.
The solution that I find good - for the code and for the project lifecycle - is to switch between LocalDb and SQL standart as suggested by one of the links above from stackoverflow combined with custom fluentApi mapping settings to equalize model creation or both.
Introducing custom convention in EF as a safety net looks good too.
If anybody has a better all-round solution, for code and for dev-production both, post it.