WCF returning results from stored procedure - vb.net

I have been tasked with implementing a WCF service in VB.NET. This WCF service will be consumed by our own .NET Windows Forms application and provide data from a SQL Server database. The data will be displayed in a third party grid (Infragistics).
Originally I was going to use ADO.NET and return a datatable or dataset from SQL within the WCF service but I have read too many articles encouraging me to stay away from returning datatables over the internet. I am not worried about the interoperability but I am worried about the size/speed of the process. This had lead me to start using linq to sql to return entities which I can pass over the internet (.dbml)
The problem:
A lot of our data comes from stored procedures, these stored procedures return result sets that are a mix-match of existing tables and therefore does not match any return type. I have imported a stored procedure that returns (Auto-generated Type) however when I try and return this type over the WCF service I get this error in the tracelog:
Type
System.Data.Linq.SqlClient.SqlProvider+SingleResult'1[benchmark_prd_colour_findResult]
cannot be serialized. Consider marking it with the
DataContractAttribute attribute, and marking all of its members you
want serialized with the DataMemberAttribute attribute. If the type
is a collection, consider marking it with the
CollectionDataContractAttribute. See the Microsoft .NET Framework
documentation for other supported types.
Please let me know what I need to be doing to be able to return the results of a stored procedure when the results don't match any particular existing table

Translate it to VB! (Sorry, didnt see the tag... Assumed C#)
Build your own object - and mark this up like this:
[DataContract]
public class MyObject{
//here go all your fields which match whats returned in your stored proc
[DataMember]
public String MyField;
[DataMember]
public int MySecondField;
}
Then populate this when getting the result of your stored proc
public MyObject GetResult(){
stored_proc_result result = factory.callProc(); //obviously replace this with whatever you use!
MyObject obj = new MyObject{
MyField = FieldOne,
MySecondField = FieldTwo
};
return obj;
}
Then if you pass the MyObject instance in your WCF call it should work.

Related

Need of serialization

I'm new to serialization concept, please help in understanding concept.
What exactly serialization means? I have read the definition, but could not understand in details.
How basic types (int, string) are serialized?
If we don't use serialization in our code how data will be transmitted?
Is there any implicit serialization process involved while accessing database from front end Java/C# code? example insert/delete from database.
Serialization just takes an object and translates it into something simpler. Imagine that you had an object in C# like so:
class Employee
{
public int age;
public string fullname;
}
public static void Main()
{
var john = new Employee();
john.age = 21;
john.fullname = "John Smith";
var matt = new Employee();
matt.age = 44;
matt.fullname = "Matt Rogers";
...
This is C# friendly. But if you wanted to save that information in a text file in CSV format, you would end up with something like this:
age,fullname
21,John Smith
44,Matt Rogers
When you write a CSV, you are basically serializing information into a different format - in this case a CSV file. You can serialize your object to XML, JSON, database table(s), memory or something else. Here's an example from Udemy regarding serialization.
If you don't serialize, confusion will be transmitted. Perhaps your object's ToString() will be implictly called before transmission and whatever result gets transmitted. Therefore it is vital to convert your data to something that is receiver friendly.
There's always some serialization happening. When you execute a query that populates a DataTable, for example, serialization occurred.
Concept :
Serialization is the process of converting an object into series of bytes.
Usually the objects we use in application will be complex and all of them can be easily represented in the form of series of bytes which can be stored in the file/database or transfered over network.
You can make a class Serializable just by making it implement Serializable interface.
For a class to be serialized successfully, two conditions must be met:
The class must implement the java.io.Serializable interface.
All of the fields in the class must be serializable. If a field is not serializable, it must be marked transient.
When the program is done serializing, and if it is stored in a file with extension .ser then it can be used for deserializing.
Serialization gives an serialVersionUID to the serialized object which has to match for deserialization

WCF Serialised List object giving strange names for objects

Here is the Method signature in the WCF service:
APIMessageList<APISimpleContact> GetMembers(string apiKey, APIContactSearchFilter filter);
APIMessageList inherits from IList. Once I have built a proxy against this WCF service the class name is APIMessageListOfAPISimpleContactjHldnYZV.
Why do I not get: APIMessageListOfAPISimpleContact?
It adds random text to the end of every APIMessageList object in the interface (there are several) They all end with the same few chars - jHldnYZV. I have looked online for possible causes, but I can't find any posts of people having this problem.
This is a purely cosmetic issue but this interface is exposed to our external customers so its appearance is important.
Anybody know why I am getting this problem?
Many thanks
Joe
Your solution will be at http://msdn.microsoft.com/en-us/library/ms731045.aspx. Basically, since you could have multiple "SimpleContract" classes (in different namespaces), WCF will add a disambiguation hash to the end of the contract name, which is what you have in the 8 chars at the end of the contract name. But you can control that, by using the CollectionDataContract and its Name property:
[CollectionDataContract(Name = "APIMessageListOfSimpleContract")]
public class APIMessageList : IList<SimpleContract> { ... }
We had a similar problem while using Generic types for return values. If we are not specifying a concrete type, the default data contract serializer or the WCF serializer is unable to infer the exact type of the returned entity. Hence it generates a random class name for the returned type.
In our project we overcame this problem by building a data contract which was of specific type and returned the same as a result of a WCF operation call.
My guess is that you are using a generic type and the serializer is unable to infer the type of the returned object.
I suggest you create a Data Transfer Object (DTO) and return the same from the WCF service. That should solve your problem.

WCF Service Contract

I have a problem using an custom data type in a WCF service method, below is my sample code
[ServiceContract()]
public class SampleServise : ISampleServise
{
void object GetSomething(ICustomData objectData)
{
// Do Something
}
}
What shall I do with ICustomData class interface?
Thanks
Afshin
WCF is based on message passing, and that message passing is modelled using XML schema (XSD). As such, whatever can be expressed in XML schema can be used in WCF.
This also means: interfaces are not supported. You need to use actual, concrete types for the parameters in your WCF service methods.
In your case, create a concrete class that implements ICustomData and then use that class as the parameter type.
For a good reference, read MSDN Designing Service Contracts which states for parameters:
Parameters and Return Values
Each operation has a return value and a parameter, even if these are
void. However, unlike a local method, in which you can pass references
to objects from one object to another, service operations do not pass
references to objects. Instead, they pass copies of the objects.
This is significant because each type used in a parameter or return
value must be serializable; that is, it must be possible to convert an
object of that type into a stream of bytes and from a stream of bytes
into an object.

WCF proxy always showing an array and not a List<T>

I'm using WSSF in Visual studio 2010 sp1 and I'm having an issue with WCF collections. It seems that when I create a service reference and change the advanced setting to use a Generic list instead of an array. I still get arrays when trying to use the collections. I would have to convert the array back and forth to a list whenever i want to add or remove objects.
Does anyone know why? or what i need to change for it to work ok. In the data contract designer, i have two types of collections. One is a "Data Contract Collection", another one is "Primitive Data Type Collection".
Any help is appreciated.
I haven't used WSSF but at a base level WCF ILists are handled as arrays. You would have to manually serialise the DTO as a List. Perhaps that's what's happening underneath the covers?
[DataMember]
public IList<Blah> BlahList
{
get { return blah; }
set { blah= new List<Blah>(value);
}
private List<Blah> blah;

How to make a return type for a result set in LINQ

I am having a problem determining how c# and LINQ solve the common problem of handling a data structure that does not necessarily return a table structure, but instead a resultset.
I have a stored procedure that works, and have included it in my DBML
[Function(Name="dbo.p_GetObject")]
public int p_GetObject([Parameter(Name="ObjectType", DbType="NVarChar(200)")] string objectType, [Parameter(Name="ItemState", DbType="Bit")] System.Nullable<bool> itemState, [Parameter(Name="IsPublished", DbType="Bit")] System.Nullable<bool> isPublished)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), objectType, itemState, isPublished);
return ((int)(result.ReturnValue));
}
The dbml says that the return type is (None) and this could be the crux issue. However I don't have a DBML object that matches the resultset.
The SP takes three parameters, and returns a result set with three columns (ID, Name, Value) with multple rows. I can create a data object for this, and call it resultSet
When I write a function call for this, I get stuck:
public List<resultset> GetObject(string objectType, bool itemState, bool isPublished)
{
MyDataContext.p_GetObject(objectType, itemState, isPublished);
}
My questions are:
how do I have the data context call to the stored procedure populate my resultSet object? Is there a better approach? What should the return type be? A SQL view? Looking for good suggestions...
If it simply isn't understanding your SP, that could be the SET FMT_ONLY issue... try generating the data from a simplified version of the SP?
Normally, SPs / UDFs that don't map 1:1 with an existing entity would expose themselves in a generated type. You can rename this in the DBML file (not in the designer), but personally I wouldn't; I tend to mark the SP as private, and write my own method that projects into my own POCO type (defined for the repository):
var typed = from row in cxt.SomeFunction(123)
select new MyType {Id = row.Id, Name = row.Name, ...}
The reason for this is partly for repository purity, and partly to guard against the designer's habit of re-writing the DBML in unexpected ways ;-p See here for more.