Complex rule for XPO class - devexpress

I want to accomplish a simple rule for an XPO class.
The situation is as :
- I have a Vehicle class :
public class Vehicle : BaseObject
{
public Vehicle(Session session)
: base(session)
{
}
public override void AfterConstruction()
{
base.AfterConstruction();
}
//...properties
[Association, DevExpress.Xpo.Aggregated]
public XPCollection<MeterEntry> MeterEntries
{
get { return GetCollection<MeterEntry>("MeterEntries"); }
}
}
And a MeterEntry class :
public class MeterEntry : BaseObject
{
public MeterEntry(Session session)
: base(session)
{
}
public override void AfterConstruction()
{
base.AfterConstruction();
}
private int _MeterValue;
private DateTime _Date;
public int MeterValue
{
get
{
return _MeterValue;
}
set
{
SetPropertyValue("MeterValue", ref _MeterValue, value);
}
}
public DateTime Date
{
get
{
return _Date;
}
set
{
SetPropertyValue("Date", ref _Date, value);
}
}
[Association]
public Vehicle Vehicle { get; set; }
}
I tried this Rule:
RuleCriteria("MeterValue >= Vehicle.MeterEntries[Date <= xxx ].Max(MeterValue)")]
In the xxx I want the value of the current object's Date smtng like : TargetObject.Date but it doesn't work, any ideas ?

You need to use the ^ character.
RuleCriteria("MeterValue >= Vehicle.MeterEntries[Date <= ^.^.Date].Max(MeterValue)")]
See more about Parent Relationship Traversal Operator at: https://documentation.devexpress.com/#CoreLibraries/CustomDocument4928

Related

Save Data in Database using Unit Of Work Pattern

I have try to save data from database using Unit OF Work Pattern.But I got error.My code is:
Unit of Work code:
private PousadaManagementContext MinhaPousadaContext { get; }
public IPousadaRepository PousadaRepository { get; private set; }
public UnitOfWork
(
PousadaManagementContext minhaPousadaContext,
IPousadaRepository pousadaRepository
)
{
this.MinhaPousadaContext = minhaPousadaContext;
PousadaRepository = pousadaRepository;
}
public async Task<int> CompleteAsync()
{
return await MinhaPousadaContext.SaveChangesAsync();
}
public int Complete()
{
return MinhaPousadaContext.SaveChanges();
}
public void Dispose() => MinhaPousadaContext.Dispose();
public interface IUnitOfWork : IDisposable
{
int Complete();
Task<int> CompleteAsync ();
}
businessclass:
private UnitOfWork managementUoW { get; }
public PousadaBusiness(IUnitOfWork ManagementUoW)
{
ManagementUoW = managementUoW;
}
public async Task<Pousada> Save(Pousada p)
{
return await managementUoW.PousadaRepository.Save(p);
}
Here In Save method p all properties have value but managementUoW is null.
How to Solve this error.

DateTime.Kind set to unspecified, not UTC, upon loading from database

When I create a Buyin object the response from the ASP.NET MVC controller, (return Json(response, JsonRequestBehavior.AllowGet);, looks like this:
"Buyin": {
"Id": 95,
"PlayerSessionId": 88,
"PlayerId": 45,
"PlayerName": "Alan",
"Amount": 888,
"BuyinType": "Credits",
"Description": null,
"Authorized": true,
"SignPath": "~/Signs/Buyins\\95.png",
"Payment": null,
"CreationDate": "/Date(1477242738042)/"
},
If I convert that on Epoch Converter I get this time: GMT: Sun, 23 Oct 2016 17:12:18.042 GMT
Looking in the database the stored datetime seems to be correct:
95 NULL 1 1 2016-10-23 17:12:18.043
When the response is sent out the Kind is set to UTC.
Now I call a controller to get all my data and all of the dates have several hours added to it:
{
"Id": 95,
"PlayerSessionId": 88,
"PlayerId": 45,
"PlayerName": "Alan",
"Amount": 888,
"BuyinType": "Credits",
"Description": null,
"Authorized": true,
"SignPath": "~/Signs/Buyins\\95.png",
"Payment": null,
"CreationDate": "/Date(1477267938043)/"
}
1477267938043 = GMT: Mon, 24 Oct 2016 00:12:18.043 GMT
However when I request this object I can see that the actual object has the correct date set:
But the Kind is set to Unspecified so I think this is causing the problem.
For the moment I don't have not set any globalization settings.
So basically my question is: When ASP.NET MVC loads the dates from the database is there a way to tell the server to load the dates with Kind set to UTC as I think that is the problem?
The database is saved and loaded using Entity Framework.
Update after the accepted answer
The accepted answer was great however my date values was already stored in the Database as UTC dates so I modified GetDateTime to this:
public override DateTime GetDateTime(int ordinal)
{
var date = base.GetDateTime(ordinal);
var utcDate = DateTime.SpecifyKind(date, DateTimeKind.Utc);
return utcDate;
//return base.GetDateTime(ordinal).ToUniversalTime();
}
Assuming you are using EF6 and you want to set the Kind property of any DateTime value retrieved from the database to Utc.
Similar questions have been asked, and the answers tend to suggest hooking into the ObjectContext.ObjectMaterialized event, but it didn't fire for queries that use projection.
The solution I'm going to propose works for both entity and projection queries, by performing the conversion at the DbDataReader level (which is used by this type of queries).
In order to do that, we need a custom DbDataReader implementation that intercepts the GetDateTime method. Unfortunately implementing DbDataReader derived class requires a lot of boilerplate code. Luckily I already created a base class form my answer to Dynamic Translate to avoid C# syntax errors which simply delegates each method to the underlying DbDataReader instance, so I'll just take it from there:
abstract class DelegatingDbDataReader : DbDataReader
{
readonly DbDataReader source;
public DelegatingDbDataReader(DbDataReader source)
{
this.source = source;
}
public override object this[string name] { get { return source[name]; } }
public override object this[int ordinal] { get { return source[ordinal]; } }
public override int Depth { get { return source.Depth; } }
public override int FieldCount { get { return source.FieldCount; } }
public override bool HasRows { get { return source.HasRows; } }
public override bool IsClosed { get { return source.IsClosed; } }
public override int RecordsAffected { get { return source.RecordsAffected; } }
public override bool GetBoolean(int ordinal) { return source.GetBoolean(ordinal); }
public override byte GetByte(int ordinal) { return source.GetByte(ordinal); }
public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) { return source.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length); }
public override char GetChar(int ordinal) { return source.GetChar(ordinal); }
public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) { return source.GetChars(ordinal, dataOffset, buffer, bufferOffset, length); }
public override string GetDataTypeName(int ordinal) { return source.GetDataTypeName(ordinal); }
public override DateTime GetDateTime(int ordinal) { return source.GetDateTime(ordinal); }
public override decimal GetDecimal(int ordinal) { return source.GetDecimal(ordinal); }
public override double GetDouble(int ordinal) { return source.GetDouble(ordinal); }
public override IEnumerator GetEnumerator() { return source.GetEnumerator(); }
public override Type GetFieldType(int ordinal) { return source.GetFieldType(ordinal); }
public override float GetFloat(int ordinal) { return source.GetFloat(ordinal); }
public override Guid GetGuid(int ordinal) { return source.GetGuid(ordinal); }
public override short GetInt16(int ordinal) { return source.GetInt16(ordinal); }
public override int GetInt32(int ordinal) { return source.GetInt32(ordinal); }
public override long GetInt64(int ordinal) { return source.GetInt64(ordinal); }
public override string GetName(int ordinal) { return source.GetName(ordinal); }
public override int GetOrdinal(string name) { return source.GetOrdinal(name); }
public override string GetString(int ordinal) { return source.GetString(ordinal); }
public override object GetValue(int ordinal) { return source.GetValue(ordinal); }
public override int GetValues(object[] values) { return source.GetValues(values); }
public override bool IsDBNull(int ordinal) { return source.IsDBNull(ordinal); }
public override bool NextResult() { return source.NextResult(); }
public override bool Read() { return source.Read(); }
public override void Close() { source.Close(); }
public override T GetFieldValue<T>(int ordinal) { return source.GetFieldValue<T>(ordinal); }
public override Task<T> GetFieldValueAsync<T>(int ordinal, CancellationToken cancellationToken) { return source.GetFieldValueAsync<T>(ordinal, cancellationToken); }
public override Type GetProviderSpecificFieldType(int ordinal) { return source.GetProviderSpecificFieldType(ordinal); }
public override object GetProviderSpecificValue(int ordinal) { return source.GetProviderSpecificValue(ordinal); }
public override int GetProviderSpecificValues(object[] values) { return source.GetProviderSpecificValues(values); }
public override DataTable GetSchemaTable() { return source.GetSchemaTable(); }
public override Stream GetStream(int ordinal) { return source.GetStream(ordinal); }
public override TextReader GetTextReader(int ordinal) { return source.GetTextReader(ordinal); }
public override Task<bool> IsDBNullAsync(int ordinal, CancellationToken cancellationToken) { return source.IsDBNullAsync(ordinal, cancellationToken); }
public override Task<bool> ReadAsync(CancellationToken cancellationToken) { return source.ReadAsync(cancellationToken); }
public override int VisibleFieldCount { get { return source.VisibleFieldCount; } }
}
and build the actual class that we need on top of it:
class UtcDateTimeConvertingDbDataReader : DelegatingDbDataReader
{
public UtcDateTimeConvertingDbDataReader(DbDataReader source) : base(source) { }
public override DateTime GetDateTime(int ordinal)
{
return DateTime.SpecifyKind(base.GetDateTime(ordinal), DateTimeKind.Utc);
}
}
Once we have that, we need to plug it into EF infrastructure using EF interception.
We'll start by creating a custom DbCommandInterceptor derived class:
class UtcDateTimeConvertingDbCommandInterceptor : DbCommandInterceptor
{
public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
base.ReaderExecuted(command, interceptionContext);
if (!(interceptionContext.Result is UtcDateTimeConvertingDbDataReader)
&& interceptionContext.Result != null
&& interceptionContext.Exception == null)
interceptionContext.Result = new UtcDateTimeConvertingDbDataReader(interceptionContext.Result);
}
}
register it (for instance from your DbContext derived class static constructor):
public class YourDbContext : DbContext
{
static YourDbContext()
{
DbInterception.Add(new UtcDateTimeConvertingDbCommandInterceptor());
}
// ...
}
and we are done.
Now every DateTime value coming from the database will have Kind property set to Utc.

xml serialization error on bool types

I am trying to find out how to solve the problem for serializing a type of bool from a camel case string.
I have the following xml
<Root>
<BoolElement>
False
</BoolElement>
</Root>
and the following class
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public bool BoolElement{get;set;}
}
this will produce an error.
If I use the same class and rename the "False" to "false" it will work. The problem is that I can't edit the xml.
Does anyone know how can I solve this?
You could use a backing field to aid for the deserialization of this invalid XML (I say invalid because according to the xsd:boolean schema False is an invalid value):
[XmlRoot("Root")]
public class RootObj
{
[XmlElement("BoolElement")]
public string BackingBoolElement
{
set
{
BoolElement = bool.Parse(value.ToLower());
}
get
{
return BoolElement.ToString();
}
}
[XmlIgnore]
public bool BoolElement { get; set; }
}
False is not a valid value for an xsd:boolean (but as you note false and 0 are) - if you cannot change the source data, then you could have a separate property purely for XML serialisation:
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public string BoolElementForSerialization
{
get
{
return (this.BoolElement ? "True" : "False");
}
set
{
this.BoolElement = (string.Compare(value, "false", StringComparison.OrdinalIgnoreCase) != 0);
}
}
[XmlIgnore]
public bool BoolElement{get;set;}
}
I created a new Boolean type that can deserialize from any string. It may not be perfect but it suited my needs at the time.
For the class you want to use simply change the data type from bool to SerializableBoolean:
[XmlRoot("Root")]
public class RootObj{
[XmlElement("BoolElement")]
public SerializableBoolean BoolElement{get;set;}
}
You can then use the BoolElement property like any normal bool data type:
RootObj myObj = new RootObj();
if (myObj.BoolElement) { ... }
Here is the code for the SerializableBoolean class, note this code only handles deserializing, serializing to xml wasn't required for my purposes and so not implemented.
[System.Diagnostics.DebuggerDisplay("{Value}")]
public struct SerializableBoolean: System.Xml.Serialization.IXmlSerializable
{
private bool Value { get; set; }
public override bool Equals(object obj)
{
if (obj is string stringBoolean)
{
bool.TryParse(stringBoolean, out bool boolean);
return Value == boolean;
}
else if (obj is bool boolean)
{
return Value == boolean;
}
else if (obj is SerializableBoolean serializableBoolean)
{
return Value == serializableBoolean.Value;
}
else
{
return Value == Convert.ToBoolean(obj);
}
}
public override int GetHashCode()
{
return -1937169414 + Value.GetHashCode();
}
public XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
Value = Convert.ToBoolean(reader.ReadElementContentAsString());
}
public void WriteXml(XmlWriter writer)
{
throw new NotImplementedException();
}
public static bool operator ==(SerializableBoolean obj1, bool obj2)
{
return obj1.Value.Equals(obj2);
}
public static bool operator !=(SerializableBoolean obj1, bool obj2)
{
return !obj1.Value.Equals(obj2);
}
public static implicit operator SerializableBoolean(string value)
{
return new SerializableBoolean() { Value = Convert.ToBoolean(value) };
}
public static implicit operator SerializableBoolean(bool value)
{
return new SerializableBoolean() { Value = value };
}
public static implicit operator bool(SerializableBoolean b)
{
return b.Value;
}
}

Interface Implementation Issue

I Have a Base Interface Like this
public interface IHRMISBaseConnector
{
IHRMISEmployeeConnector EmployeeConnector { get ; set; }
}
And i have one more interface like this
public interface IHRMISEmployeeConnector
{
String Add(EmployeeDetails e);
Boolean Update(EmployeeDetails e);
Boolean Delete(int id);
}
I want implement IHRMISBaseConnector in this class DDWEDocumentOperations
How can i implement ? Please let me know if anybody knows it
Something like this should help you:
class FakeImplementationOfEmployeeConnector : IHRMISEmployeeConnector
{
public string Add(EmployeeDetails e)
{
//...
}
public bool Update(EmployeeDetails e)
{
//...
}
public bool Delete(int id)
{
//...
}
}
class DDWEDocumentOperations : IHRMISBaseConnector
{
IHRMISEmployeeConnector employeeConnector = new FakeImplementationOfEmployeeConnector();
public IHRMISEmployeeConnector EmployeeConnector
{
get
{
return employeeConnector;
}
set
{
employeeConnector = value;
}
}
}
Here is an example:
public class DDWEDocumentOperations : IHRMISBaseConnector
{
private IHRMISEmployeeConnector _employeeConnector;
public IHRMISEmployeeConnector EmployeeConnector
{
get { return _employeeConnector; }
set { _employeeConnector = value; }
}
}

Using a session wrapper for replacing direct call to session variables

I use a session wrapper like this:
public interface ISessionWrapper
{
// ...
CultureInfo Culture { get; set; }
}
public class SessionWrapper: ISessionWrapper
{
private T GetFromSession<T>(string key)
{
return (T)HttpContext.Current.Session[key];
}
private void SetInSession(string key, object value)
{
HttpContext.Current.Session[key] = value;
}
// ...
public CultureInfo Culture
{
get { return GetFromSession<CultureInfo>("Culture"); }
set { SetInSession("Culture", value); }
}
}
I can use this interface in my controller like this:
private readonly ISessionWrapper sessionWrapper = new SessionWrapper();
// ...
ci = new CultureInfo(langName);
sessionWrapper.Culture = ci;
But how can I access this wrapper in the view below to replace the (direct call to) session variable?
#switch (Session["Culture"].ToString())
{
case "fr":
// ...
case "uk":
// ...
}
You could make use of the base view:
public abstract class BaseViewPage : WebViewPage
{
public virtual ISessionWrapper SessionWrapper
{
get
{
return new SessionWrapper();
}
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual ISessionWrapper SessionWrapper
{
get
{
return new SessionWrapper();
}
}
}
your views will have access to SessionWrapper property.
Make sure to add pageBaseType="SessionWrapper" attribute to pages tag in web.config.

Resources