Sure, there is a way of doing it without trigger. Doing it without a trigger will work with any database supported by Entity Framework providers...
Unfortunately, I am not sure about Designer First approach but with Code First you can do it like this(it's probably similar with Designer First, maybe using partial class). Looking forward, if possible, you should use Code First, because it's only way supported by new Entity Framework Core.
Model:
public abstract class ConcurrencyTracker
{
[ConcurrencyCheck]
public long LastChange { get; set; }
[NotMapped]
public DateTime LastChangeTime
{
set
{
long timestamp = value.Ticks - new DateTime(1970, 1, 1).Ticks;
timestamp = timestamp / TimeSpan.TicksPerSecond;
LastChange = timestamp;
}
}
}
public class Product : ConcurrencyTracker
{
public int Id { get; set; }
public string Name { get; set; }
}
Context:
public override int SaveChanges()
{
var currentTime = DateTime.Now;
var changed = ChangeTracker.Entries<ConcurrencyTracker>().Where(c => c.State != EntityState.Unchanged);
if (changed != null)
{
foreach (var item in changed)
{
item.Entity.LastChangeTime = currentTime;
}
}
return base.SaveChanges();
}
EF will include LastChange column in all updates of Product model so there is optimistic concurrency.