I have a WCF service and a WPF application in my solution.
The application contains objects I made (customer, products etc), my windows and my business logic.
I need to retrieve a list of customers using the service but the service doesn't know what is a customer.
I CAN put all of my objects in both projects or reference one project from the other but that doesn't seem like the right way.
Any idea what should I do here?
Use data contract in your service like.
[DataContract]
public class Customer
{
[DataMember]
public int CustomerID{ get; set; } }
[DataMember]
public string CustomerName{ get; set; }
}
public interface ICustomerService
{
[OperationContract]
List<Customer> GetAllCustomer();
}
public Class CustomerService:ICustomerService
{
List<Customer> GetAllCustomer()
{
// write your own code to fill List<Customer> ans return it
}
}
Thanks
Ck Nitin (TinTin)
When will add the service reference of WCF or add the .dll in which WCF service is define in case if you are calling the WCF service from code using ServiceHost class, you can create the object for this customer class and you can easily use it.
Thanks
Ck Nitin (TinTin)
Related
Look at this complex type, which is basically a DTO that wraps some entities. I don't need to track these entities or use the for updating or any of that stuff, I just want to send them down to the client. The stuff at the top are non-entities just to let me know that I'm not crazy.
public class ResultDetail
{
// non entities (some are even complex) - this works GREAT!
public string WTF { get; set; }
public IEnumerable<int> WTFs { get; set; }
public SomethingElse StoneAge { get; set; }
public IEnumerable<SomethingElse> StoneAgers { get; set; }
// these are entities - none of this works
public EntityA EntityA { get; set; }
public IEnumerable<EntityB> EntityB { get; set; }
}
public class SomethingElse
{
public int ShoeString { get; set; }
}
Now look at this:
http://i.snag.gy/tI9O9.jpg
Not a single entity property shows up on the client side generated types. Are there attributes or something that I can or do I really need to create DTO objects for every one of these entity types? There are more than 2 as in my sample and they have many properties.
By the way these entity types have been generated on the client because of the normal query operations in the domain service that work with them.
This is not possible as current Ria services framework is mainly designed for tracking entities, and for Ria services it is not possible to detect which properties to serialized and which to note, since every entity has navigation properties, serializing properties may cause infinite loops or long loops as there is no control over how to navigate object graph.
Instead you are expected to program your client in such way so that you will load relations on demand correctly.
I've created a complex object which itself include a list of another object.
Example:
public class MyClass1
{
private List<MyClass2> myClass2List
[Key]
public long Id { get; set; }
public string Name { get; set; }
[Include]
[Association("FK_MyClass1_MyClass2", "Id", "MyClass1Id")]
public List<MyClass2> MyClass2List
{
get
{
if (this.myClass2List == null)
{
this.myClass2List = new List<MyClass2>();
}
return this.myClass2List;
}
set { this.myClass2List = value; }
}
}
public class MyClass2
{
[Key]
public long Id { get; set; }
public string Value { get; set; }
public long MyClass1Id { get; set; }
}
Now I want to send an instance of MyClass1 (which its MyClass2List is full) to the RIA services.
My first try was creating a get method with MyClass1 return type (to expose MyClass1) and also creating an Insert method for MyClass1 and MyClass2. It works but the MyClass2 Insert method is useless! I insert all the information in MyClass1 method. Also the get method is useless!
This is the domain service that works:
[EnableClientAccess]
public class MyDomainService : DomainService
{
public MyClass1 GetMyClass1()
{
return null;
}
[Insert]
public void Insert(MyClass1 myClass1)
{
... (Main code)
}
[Insert]
public void Insert(MyClass2 myClass2)
{
// I leave this method empty because I do the job in MyClass1 Insert method.
// If I don't add this method the Add operation on MyClass2List will not work!
}
}
As you see it doesn't have a clear implementation. Although I could use the traditional WCF Silverlight-Enabled services and simply use a single method to insert the MyClass1 instance.
Note that I tried the [Invoke] method (A simple invoke method which gives the MyClass1 as an input parameter) but then "MyClass1.MyClass2List" is empty!!!
How can I send a complex object to RIA services without having such useless methods and dirty implementation? I need to do all my works just in a single method. I don't need tracking and etc here. Is it better to use the traditional WCF Services besides the RIA or is there another way about RIA?
Thanks in advance
You need to add [Composition] attribute to your one-to-many relationships as well. more info:[ +, +, + ]
Also Try to switch to "RIA Services EF Code First Support"
On the client you just call SubmitChanges on the domain context. RIA then calls the appropriate insert methods for you.
I am struggling with returning a complex type from my services layer. It doesnt seem to be accessible from my object context.
This is the query in the service layer. All compiling fine.
public IQueryable<USP_GetPostsByThreadID_Result> uspGetPostsByThreadID(int ThreadID)
{
return this.ObjectContext.USP_GetPostsByThreadID(ThreadID).AsQueryable();
}
When I try and call it from my client, the ForumContext is not seeing it. I checked the client generated file and nothing similar is being generated. Help!!!
The name of your method may not meet the expected convention for queries. Try one or both of the following:
Add the [Query] attribute
Rename the method to GetUspPostsByThreadID
Result:
[System.ServiceModel.DomainServices.Server.Query]
public IQueryable<USP_GetPostsByThreadID_Result> GetUspPostsByThreadID(int ThreadID)
{
return this.ObjectContext.USP_GetPostsByThreadID(ThreadID).AsQueryable();
}
Its very common to have a stored procedure returning data from multiple tables. The return type doesn't fit well under any of the Entity Types(Tables). Therefore if we define Complex Type as the return collection of objects from Stored Procedure invocation, it becomes quite a powerful tool for the developer.
Following these steps I have achieved successfully the configuration of complex type on a sample AdventureWorks database.
1. Refer the picture and ensure the Stored procedure and function import is done.
2. Add the Domain Service name it as AdventureDomainService.
3. Now its time to define the tell the RIA services framework to identify my Complex Type as Entity Type. To be able to do this, we need to identify a [Key] DataAnnotation. Entity types provide data structure to the application's data model and by design, each entity type is required to define a unique entity key. We can define key on one property or a set of properties in metadata class file AdventureDomainService.metadata.cs
First define the class then add MetadatatypeAttribute like :
[MetadataTypeAttribute(typeof(CTEmployeeManagers.CTEmployeeManagersMetadata))]
public partial class CTEmployeeManagers
{
internal sealed class CTEmployeeManagersMetadata
{
private CTEmployeeManagersMetadata() { }
[Key]
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int ManagerID { get; set; }
public string ManagerFirstName { get; set; }
public string ManagerLastName { get; set; }
}
}
Define the Domain service method to return the collection of objects/entities for populating the Silverlight Grid or any other data consuming controls.
public IQueryable<CTEmployeeManagers> GetEmployeeManagers(int empId)
{
return this.ObjectContext.GetEmployeeManagers(empId).AsQueryable();
}
We define IQueryable if we are to fetch the records from datasources like SQL, whereas we define IEnumerable if we are to fetch the records from in memory collections,dictionaty,arrays.lists, etc.
Compile the server side to generate the client proxy.
In the Silverlight side open the MainPage.xaml or wherever the datagrid is put, then add following namespaces :
using System.ServiceModel.DomainServices.Client;
using SLBusinessApplication.Web;
using SLBusinessApplication.Web.Services;
..
Load the data and display:
public partial class MyPage : Page
{
AdventureDomainContext ctx = new AdventureDomainContext();
public MyPage()
{
InitializeComponent();
LoadOperation loadOp = this.ctx.Load(this.ctx.GetEmployeeManagersQuery(29));
myGrid.ItemsSource = loadOp.Entities;
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
That is all that is needed to do.
It has to be part of an entity. Complex types cannot be returned by themselves
I have created many class as my data class i.e:
[DataContract]
public class pCity
{
[DataMember]
public string code { get; set; }
[DataMember]
public string cityName { get; set; }
[DataMember]
public string provinceCode { get; set; }
}
I know if I put them into the WCF's svc.cs file or use them in WCF then it will be added and Silverlight side will see them from the Wcf Service Client's reference.
But I don't want my wcf file getting to large, so I store them into difference classes and in another class library project, reference it in Silverlight's Web Project.
Is there a quick way I can add them all into WCF (without doing the things I described above) so I can see them in Wcf Service Client's reference.
Thanks in advance.
King
They will never show up in a client's reference unless they are actually used by the service. That is, they must be either the type of a parameter, or else be the return type from an operation.
Howdy, ya'll! First question on StackOverflow! :-)
So here's the scenario: We're working on a web app with Silverlight 4 and using WCF RIA Services 1.0 SP1 Beta for the web service. I have my entities in the Entity Framework Designer, but I'm using a slightly-modified ADO.NET C# POCO Entity Generator template to generate the classes.
What I'd like to do is have a method inside a Domain Service with the following signature:
[EnableClientAccess]
public class ResultService : DomainService
{
[Invoke]
public SerializableResult CalculateResult(EntityOne e1, EntityTwo e2);
}
I am returning both EntityOne and EntityTwo to the client through queries in other services, like so:
[EnableClientAccess]
public class EntityOneService : DomainService
{
public IQueryable<EntityOne> GetEntityOnes();
}
[EnableClientAccess]
public class EntityOneService : DomainService
{
public IQueryable<EntityTwo> GetEntityTwos();
}
Those classes are successfully being generated in the Silverlight project. The SerializableResult does not have a key.
When I try to compile, I get the following error: "Operation named 'CalculateResult' does not conform to the required signature. Parameter types must be an entity or complex type, a collection of complex types, or one of the predefined serializable types."
In my research, the most helpful information I found were in the comments of this post by Jeff Handley.
Of note, Peter asked in a comment:
I get an 'does not conform to the required signature ...' compile error if my complex object has an [Key] Attribute. When I remove this attribute I can use the object as parameter for an Invoke operation.
Jeff's response:
This is by design. Complex objects cannot have Key properties. If you have a Key the class gets treated as an Entity.
So it sounds as if any further efforts to try to get my method to work will be futile. However, I was wondering if anyone else has come across this problem, and what they did to solve it.
Thanks very much!
I have the following and it works for me.
namespace BusinessApplication2.Web
{
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
[EnableClientAccess()]
public class DomainService1 : DomainService
{
public IQueryable<EntityOne> GetEntityOnes()
{
return null;
}
public IQueryable<EntityTwo> GetEntityTwos()
{
return null;
}
[Invoke]
public SerializableResult GetSerializableResult(EntityOne one, EntityTwo two)
{
return new SerializableResult() { Result = "It woooooorrrked!" };
}
}
public class EntityOne
{
[Key]
public int Id { get; set; }
}
public class EntityTwo
{
[Key]
public int Id { get; set; }
}
public class SerializableResult
{
public string Result { get; set; }
}
}
Many thanks to Mr. Jeff Handley and Mr. Dinesh Kulkarni for the answer (through Twitter).
In order for an Entity to be used as a parameter in an invoke method, that Entity must be exposed through a query method existing within the same DomainService. The intention for this restriction is that
"Each domain service needs to be able to stand on its own."
By adding two dummy Query methods (see Jeff's answer for an example), I was able to compile my code.