I am working on an app where I am using WCF RIA services and entity framework.
On laod,i have written a method which gets a list of schedules from database(as fetched using RIA method LoadOperation<>).
I have put a breakpoint on the method,but when I debug it the list shows 0 count and when I bind the empty list to datagrid,the grid shows all records.
How's this possible.
I got stuck in between
Kindly help for the same!!!
Loading data via the DomainContext is an asynchronous operation. Binding to a grid, etc. works because LoadOperation.Entities is observable and will fill in eventually. However, if you're trying to access it in code, you will have to wait for the callback.
myContext.Load(myContext.GetMyQuery(), OnLoadCompleted, null);
private void OnLoadCompleted(LoadOperation<MyEntity> op)
{
if (op.HasError)
{
// Handle error
op.MarkErrorAsHandled();
}
else
{
IEnumerable<MyEntity> entities = op.Entities;
// now do stuff with entities
}
}
See this page for more information.
Related
We are considesing using BreezeJS as analogous solution to our current WCF Ria Services + Silverlight pair. In WCF Ria Services we have client DataContext containing EntitySet instances which get populated with queries.
For example, there we might have three methods on our DomainService described below. Assume also that User is linked to Order as 1-to-many:
public IEnumerable<User> GetFirst10Users(){
//retrieve from DB with EF
return ObjectContext.Users.OrderBy(u => u.Id).Take(10);
}
public IEnumerable<User> GetLast10Users(){
//retrieve from DB with EF
return ObjectContext.Users.OrderByDesc(u => u.Id).Take(10);
}
public IEnumerable<Order> GetOrders(){
//retrieve from DB with EF
return ObjectContext.Orders;
}
As a result we'll have something like this generated for us on client-side:
public class Context{
public EntitySet<User> Users {...};
public EntitySet<Order> Orders {...};
public EntityQuery<User> GetFirst10UsersQuery(){
}
public EntityQuery<User> GetLast10UsersQuery(){
}
public EntityQuery<Orders> GetOrdersQuery(){
}
}
If we execute first two queries, we'll end up having union of their results in Users collection. Executing the third one will give us all orders in Orders collection, but only subset of those will be contained in Navigation collections of User instances on client. It works really well and as Entities get added to Users collection(by query, or by user's action, or by other viewmodel's side effect) those get displayed on UI right away through binding to ObservableCollection wrapper over Users EntitySet.
The same gets reflected on canceling changes, and I don't need to do a lot for that - just providing observable interface.
With BreezeJS and JS particularly, it looks like that I should be subscribing to various events of Breeze and synchronize data with my Kendo UI observable array instance (which is in fact copying data between breeze cache and Kendo UI observable array).
In WCF Ria Services, Context.Users entityset has EntityAdded / EntityDeleted events which makes it possible to handle additions/removals in our ViewModels.
The same events are also available for NavigationCollections, so we might do user.Orders.EntityAdded += ... for example.
So, I'm trying to implement something similar to what we had in WCF Ria Services + Silverlight using Angular + BreezeJS + Kendo UI in TypeScript. I have kind of found analogs for EntityAdded/Deleted events for EntitySet in Breeze but didn't find anything like this for NavigationCollections.
Could someone let me know if the path I'm trying to go with is completely awkward in BreezeJS/KendoUI/Angular world? If no, how do I handle changes in navigation collections in BreezeJS?
Is there a way to read the web service methods dynamically using a program? I have a windows forms app that should be able to read the list of methods and display them. I have added a service reference to my project but need help to read the list of web methods or operations (WCF).
Answer:
Here is the piece of code just in case anyone is looking for it.
MethodInfo[] methods = typeof(MyClass).GetMethods(BindingFlags.Public | BindingFlags.Instance);
if (methods != null && methods.Length > 0)
{
foreach (MethodInfo m in methods)
{
foreach (object o in m.GetCustomAttributes(false))
{
// To identify the method
if (o.GetType().Name.Equals("SoapDocumentMethodAttribute"))
{
// Get Name using m.Name
}
}
}
}
Alternatively, if you need to read the methods of a service on-the-fly, this article may be of interest to you, as it illustrates how to create a WCF proxy from WSDL.
http://blogs.msdn.com/b/vipulmodi/archive/2008/10/16/dynamic-proxy-and-memory-footprint.aspx
Then you can use reflection (as per Mike's suggestion) to read the list of service methods exposed by the service.
On your client side, since you already have a web reference type for the web service, you can just use reflection to list all the methods in the proxy client class.
I have a WCF service that calls the following method in one of my Repository objects to create a new sale object in the database
public static Sale New(Sale sale)
{
using (var ctx = new DBcontext())
{
ctx.Sales.AddObject(sale);
ctx.SaveChanges();
return sale;
}
}
The WCF method calling this looks like this
public Sale SaleNew(Sale sale)
{
return SaleRepository.New(sale);
}
When I call this from a client application I get the following error
"The underlying connection was closed: The connection was closed unexpectedly."
If I step through all the code seems to run fine and the record gets insterted into the database. If I add the following line to my repository method after the SaveChanges it works fine
ctx.Detach(sale);
Is the exception happening because I'm disposing the context as soon as the method returns? Is using the entity context in this way bad practise ie disposing of it straight away? I'm only doing this because its SOA and pretty much stateless so all my repository methods create the context return the value and dispose the context. Anything that is passed in will either get added to the context or re-attached.
As advised I turned on tracing in WCF and watched what was happening. There was a proxy exception occurring. In this case as I'm using my own POCO objects I don't really want proxy objects so I set the ContextOptions.ProxyCreationEnabled property in my DatabaseContext to false and it now works fine.
1) Is using the entity context in this way bad practise ie disposing of it straight away?
No, that's how I do it - and I believe it is the proper way of doing it. But creating context can be expensive and with EF we are stuck with no ideal way of reusing the context.
2) ctx.Detach(sale);
This as far as I know should not be required for what you are doing although I have had loads of issues with attaching and detaching when I reuse the same entities. This should be only needed if you need to re-attach to context. Are you using Lazy-Loading?
I am using WCF and REST, and I have complex types, which are working fine. Now I need to check for validation, I am thinking of using DataAnnotations e.g.
public class Customer
{
[Required]
public string FirstName {get;set;}
}
Now where the issue is how do I pass this validation down to the REST service?
ALso I need to validate the object when it comes back, and throw an exception, if I am to throw an exception then what is the best way of doing this using REST?
I would use the Validation Application Block included in the Microsoft Enterprise Library to validate the data transfer objects being used in the service interface. You can use attributes to decorate the objects' properties with validation rules, much in the same way as with the ASP.NET Data Annotations.
In case validation fails you should return an appropriate HTTP Error Code and include the details of what went wrong in the HTTP response.
Here is an example:
public void PostCustomer(Customer instance)
{
ValidationResults results = Validation.Validate(instance);
if (!results.IsValid)
{
string[] errors = results
.Select(r => r.Message)
.ToArray();
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.BadRequest;
WebOperationContext.Current.OutgoingResponse.StatusDescription = String.Concat(errors);
}
// Proceed with custom logic
}
If you are using the WCF REST Starter Kit, you should instead throw a WebProtocolException, as described in this article.
I would look into writing a custom IDispatchMessageInspector implementation where, in the AfterReceiveRequest method, you manually invoke the validation architecture.
I won't go into the details of how to call the Data Annotations validation architecture as I'm sure you can find that somewhere online if you don't already know how to do it. That said, once you have your validation results you can enumerate them and then, if there are any failed validations, you can throw a generic validation fault filled with the details from the AfterReceiveRequest implementation.
this is a weird thing.
I created a simple SOAP based web service with WCF. When the 'SubmitTransaction' method is called, the transaction is being passed on to an application service. But if the application service is not available, it is being written to a MSMQ.
Like this:
public void SubmitTransaction(someTransaction)
{
try
{
// pass transaction data to application
}
catch(SomeError)
{
// write to MSMQ
}
}
So when an error occures the transaction is written to the queue. Now, when using the MSMQ API directly in my WCF service, everything is fine. Each call takes a few milliseconds.
E.g.:
...
catch(SomeError)
{
// write to MSMQ
var messageQueue = new MessageQueue(queuePath);
try
{
messageQueue.Send(accountingTransaction, MessageQueueTransactionType.Single);
}
finally
{
messageQueue.Close();
}
}
But since I want to use the message queue functionality at some other points of the system as well, I created a new assembly that takes care of the message queue writing.
Like:
...
catch(SomeError)
{
// write to MSMQ
var messageQueueService = new MessageQueueService();
messageQueueService.WriteToQueue(accountingTransaction);
}
Now when using this setup, the web service is suddenly very slow. From the above-mentioned milliseconds, each call now takes up to 4 seconds. Only because the message queue stuff is encapsulated in a new assembly. The logic is exactly the same. Anyone knows what the problem could be...?
Thanks!
Ok, now I know. It has something to do with my logging setup (log4net). I'll have to check that first. Sorry for stealing your time..
You have two new lines of code here:
var messageQueueService = new MessageQueueService();
messageQueueService.WriteToQueue(accountingTransaction);
Do you know which of the two is causing the problem? Perhaps add some logging, or profiling, or step through in a debugger to see which one seems slow.