Is there anything which can be use to avoid using Order attribute in DataMember while passing parameters from xml to WCF service
[DataMember(Name = "Name", Order = 2)]
...
[DataMember(Name = "ID", Order = 1)]
...
No there is no way of avoiding using the Order DataMemberAttribute if you are passing members in an order which differs from those that the serializer are expecting.
The rules for ordering are outlined here:
http://msdn.microsoft.com/en-us/library/ms729813.aspx
The basic rules for data ordering include:
If a data contract type is a part of an inheritance hierarchy, data members of its base types are always first in the order.
Next in order are the current type’s data members that do not have the Order property of the DataMemberAttribute attribute set, in
alphabetical order.
Next are any data members that have the Order property of the DataMemberAttribute attribute set. These are ordered by the value of
the Order property first and then alphabetically if there is more than
one member of a certain Order value. Order values may be skipped.
If you pass members which do not conform to these rules then you will get null values as the serializer will skip them. I know it's not great but this is unfortunately the way it works.
Related
All the examples I am finding for using the AliasToBean transformer use the sessions CreateSqlQuery method rather than the CreateQuery method. They also only return the basic value types, and not any object's of the existing mapped types.
I was hoping it would be possible that my DTO have a property of one of my mapped Domain objects, like below, but I am not getting traction. I get the following exception:
Could not find a setter for property '0' in class 'namespace.DtoClass'
My select looks like the following on my mapped classes (I have confirmed the mappings pull correctly):
SELECT
fcs.MeasurementPoint,
fcs.Form,
fcs.MeasurementPoint.IsUnscheduled as ""IsVisitUnscheduled"",
fcs.MultipleEntryAllowed
FROM FormCollectionSchedule fcs
My end query will be more complex, but I wanted to confirm if this AliasToBean method can return mapped domain objects as well as basic field values from tables retrieved via sql.
the query execution looks like the following:
var result = session.CreateQuery(hqlQuery.ToString())
.SetResultTransformer(NHibernate.Transform.Transformers.AliasToBean(typeof (VisitFormCollectionResult)))
.List<VisitFormCollectionResult>();
note: the VisitFormCollectionResult DTO has more properties, but I wanted to know if I could populate the domain object properties matching the names
update found my problem! I have to explicitly alias each of the fields. once I added an alias, even though the member property on the class matched my DTO's property name, the hydration of the object worked correctly.
The answer to my own question was that each of the individual fields in the select needed an explicit alias matching the property, regardless if the field name already matched the property name of the DTO object:
SELECT
fcs.MeasurementPoint as "MeasurementPoint",
fcs.Form as "Form",
fcs.MeasurementPoint.IsUnscheduled as "IsVisitUnscheduled",
fcs.MultipleEntryAllowed as "MultipleEntryAllowed"
FROM FormCollectionSchedule fcs
I have a base entity, and a derived entity, with an extra boolean property. My WCF Data Service exposes an EntitySet of the base entity. I can query it in a browser:
http://myserver/myservice/BaseSet/Namespace.Derived()?$filter=(BoolProp eq false)
And I get a collection of objects of my Derived type. All good.
In my client I have a grid which takes a DataServiceQuery. So I constructed my query:
var query = context.CreateQuery<Proxy.Derived>("BaseSet");
But when I try to filter on derived properties it returns an error. And when I examined the URL it used in its request it's missing the chunk for my derived type, i.e. it looked like:
http://myserver/myservice/BaseSet()?filter=(BoolProp eq false)
What's the proper way to construct a DataServiceQuery that I can use to query using properties on my derived type?
Turns out all I needed was to extend the entitySetName argument to include my derived type:
var query = context.CreateQuery<Proxy.Derived>("BaseSet/Namespace.Derived")();
The name of the argument isn't great. Now I actually bother to read the documentation it does tell me that the entitySetName should be "A string that resolves to a URI." Not sure that helps most people but I should have checked it sooner.
Using NHibernate, I need to be able to configure my application to sort a specific collection of entities exactly as needed.
The configurable sort:
can involve multiple properties
can specify the sorted properties in any order
can specify asc/desc on the sorted properties
can sort by custom properties (i.e. there is no corresponding SQL/C# property - it is calculated)
This functionality is inherited from an existing app where parts of the SQL are specified by an administrator and the SQL statement is built/executed dynamically.
Every time I try thinking through a solution I start getting in muddy waters with all kinds of alarms going off in my head regarding maintainability, performance, scalability, security, etc..
For example, I figure the admin can specify a comma delimited string like so:
"Date asc, FirstName asc, LastName desc"
I can split the string and go through a loop matching the property/sort pairings in a case statement and calling .AddOrder(Order.Asc("FirstName")) as necessary. But then, how do I handle custom properties? I could allow the user to specify SQL for calculating custom properties and then allow the user to sort on those like they would FirstName, but I'm seemingly back at dirty/kludge again.
Is there a clean/appropriate way to handle this requirement?
After much thought and a stroke of luck, I may have a solution.
public class CustomOrder : Order
{
private string customOrderSql;
public CustomOrder(string customOrderSql) : base("", true)
{
this.customOrderSql = customOrderSql;
}
public override NHibernate.SqlCommand.SqlString ToSqlString(
ICriteria criteria, ICriteriaQuery criteriaQuery)
{
return new NHibernate.SqlCommand.SqlString(this.customOrderSql);
}
}
I can pass a custom sort string to my repository where I add my CustomOrder as follows:
.AddOrder(new CustomOrder(customSort))
I still can't sort by custom properties but maybe I can get away with applying case statements in the order by clause. I'm still open for better suggestions if they exist.
I have a type Type1 with a property Type2s consisting of a List<Type2>. I have configured the NHibernate mapping for the property as follows:
[Map(0, Table = "Type2s", Schema = "MySchema", Cascade = CascadeStyle.All, Lazy = true, Inverse = true)]
[Key(1, Column = "Type1Id")]
[OneToMany(2, Class = "Type2, MyNamespace")]
What is the difference in behavior between these two criteria for retrieval of Type1 instances:
var criteria1 = DetachedCriteria.For<MyType1>();
var criteria2 = DetachedCriteria.For<MyType1>().SetFetchMode("Type2s", FetchMode.Join);
When I invoke .List on the executable criteria from these criteria, presumably the SQL to retrieve the Type2s associated with each Type1 instance is not run until I actually attempt to access the property because the property is marked as being Lazy. Is this a correct assumption?
If I want to force evaluation of the Lazy property how can this best be achieved?
I'm not very familiar with attribute binding vs. hbm/fluent, but I believe you have solved your own problem!
You are correct assuming that the data for the Type2s will not be loaded until request because of the bag being lazy. Your second criteria's fetchmode forces those object to be hydrated at the same time, ie. in one database roundtrip.
As an aside, FetchMode.Join is equivalent to FetchMode.Eager (which is a better name re:laziness in my opinion).
article explaining it a little more in depth:
http://davidhayden.com/blog/dave/archive/2008/12/06/ImprovingNHibernatePerformanceFetchingStrategiesFetchModeFluentNHibernate.aspx
describing FetchMode.Join and FetchMode.Eager:
http://bchavez.bitarmory.com/archive/2008/04/04/differences-between-nhibernate-fetchmode.eager-and-fetchmode.join.aspx
With the XmlSerializer I can have my members in different namespaces to the parent type.
Can I do the same thing with DataContractSerializer?
I would like the following XML:
<h:Type xmlns:h="http://schemas.e.com/WebServices"
xmlns="http://schemas.e.com/WebServices">
<Member xmlns="http://schemas.e.com/CoreTypes">0</Member>
</h:Type>
Is this possible in with DataContractSerializer?
You can define subdatacontracts in different namespaces and use them as members of another datacontract, but you can't control the individual member names and/or shapes. The DataContractSerializer isn't intended to replace XmlSerializer for fine-grained control of the "shape" of your XML.
While it is true as stated in this answer by nitzmahone that a specific data contract type cannot have declared members in multiple namespaces, it is possible that, in a type hierarchy, derived types can belong to different data contract namespaces than the base types from which they inherit. When this happens, each member will be serialized into the namespace in which it is declared. By constructing an appropriate type hierarchy, XML entities with members in disparate namespaces can be (de)serialized by DataContractSerializer.
The specific rules are as follows:
If a data contract type is a part of an inheritance hierarchy, data members of its base types are always first in the order.1
Data members are serialized into the data contract namespace of the data member type in which they are declared.
The root namespace of a data contract type is the namespace of its most derived type.
XML elements are (de)serialized in the order specified by Data Member Order. DataContractSerializer does not allow for data members to be freely reordered during deserialization.2
Collections have their own rules as specified in Collection Types in Data Contracts; this answer does not apply to them.
Thus the XML in the question can be consumed by DerivedType in the following type hierarchy:
[DataContract(Name = "Base", Namespace = "http://schemas.e.com/CoreTypes")]
public class BaseType
{
[DataMember]
public int Member { get; set; }
}
[DataContract(Name = "Type", Namespace = "http://schemas.e.com/WebServices")]
public class DerivedType : BaseType
{
}
And, in general, any sequence of XML elements in any sequence of namespace(s) can be obtained by applying the rules above to construct an appropriate type hierarchy, offering a workaround that meets the requirement of deserializing elements in different namespaces.
Of course, such a hierarchy might be inconvenient for other reasons, in which case the preferred data model types can be replaced with DTOs by using the data contract surrogate mechanism.
1 Data Member Order.
2 Data Member Order and XML Deserialization