I have a database I'd like to create an entity from, and then generate RESTful output.
My objective is to add a property to one of the tables once it becomes an entity. The data for that property would be one I'd come up with through calculations done on a few different fields in the table. From there, the code generator would create RESTful output like it normally does.
I have managed to be able to update the SSDL, CSDL, and the mapping sections of the edmx file along with using the SampleEdmxCodeGenerator as a custom tool. When I have all the sections in the edmx file filled out with my custom property, the svc fails because (I'm assuming) the property doesn't exist in the database. If I leave the property out of the SSDL, but put it in the client schema (CSDL) and the mapping section, I can't build my project.
I've modified the partial class and added to it, but the problem there is that I need to populate the methods on the creation time of the class, and I haven't been able to do that yet.
Am I headed in the right direction, or is this not possible? It seems like I should be able to do this with minimal effort, but I keep hitting walls.
I think you're taking detours to get where you want. I haven't used either of these approaches (recently), so they might not do exactly what you're after, but you could try this:
Create a partial class file right next to the .edmx model, which has the same name as your entity.
In it, specify the property you want as a read-only property, that does the calculations on each get.
Partial Classes and Partial methods were the first part of my answer. What I'm essentially trying to do I can't do. I can manipulate data that is returned by using partial methods and partial classes. I can plug the OnmethodnameChanged() method to format the data how I'd like it to be shown, but that only gets me part way to my desired result.
What I would also like to do, is create a property c, which doesn't exist as a column in the database (and therefore does not exist in my entity), calculated from a couple different properties in the database (say a and b), and then add property c to the entity framework class. In doing this, I figured it would then get generated into the RESTful webservice output.
A problem that occurs comes from the need for the class to update any changes you make, and have it propagate back to the data source. I didn't care about that, because I want my property to be read only. From what I've gathered this isn't possible.
For reference, these two posts really helped:
Adding custom property to Entity Framework class
(I can only post one url currently, so here is the address to the other article)
social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/b7a9e01d-c5c2-4478-8f01-00f7f6e0f75f
What I've decided to do, is to expose my entity as I've done so far, then consume the RESTful service that manipulates data and reformats it, and introduces needed properties. I'll turn the results into my own data object, and use that as a datasource to be exposed by yet another RESTful web service. I think this website gives a good example on how to expose a custom datasource.
mstecharchitect.blogspot.com/2008/12/surfacing-custom-data-source-in-adonet.html
If for some reason that is too slow, I suppose I could just make another table in my database that has a reworking of the data, and the calculated output in a format I'm looking for. The thing I want to avoid is having my resulting client having to do any of the data manipulation since it will be on some micro devices like palms, iphones, and blackberries.
Hope that helps anyone else with the same problem. It seems that is a shortfall in the current version of Data Services, but to some extent, I'm sure they'll be addressing it in later versions. Maybe T4 and .net 4.0 will be addressing it. I'm not sure.
Related
I've recently started developing in .NET core.
When developing I encountered the situation that I have to make very similair models that aren't quite the same. For example, let's talk about a booking model:
Frontend: Here I need a model that gets posted as a JSON to my backend and gets deserliazed to a sort of FrontendBooking model.
Backend: I need to add Customer data to the booking, therefore I need to add fields like: CustomerName and CustomerAddress, based on their CustomerId. The backend needs to provide this data, I do not want the frontend to determine these fields. I combine these models to prepare it for an API call. To a model called RequestBooking.
API: I sent RequestBooking to an API and get a response with a similair object that has for example a Status and BookingId added, this was added to the model by the API. So I need to deserialize this to an object called: ResponseBooking.
Database: Finally I wish to store the object to a database, not all properties of the model are relevant however, therefore I create another model called: DatabaseBooking and store this to the databse.
When a property is added, removed or changed. Then I'll have to change it for each of these models.
Is there a design pattern or some other solution, so this is more manageable?
Also, what is best practise for naming these models? Naming them all Booking doesn't feel quite right and adding what they're used for doesn't feel quite right either.
Thanks in advance.
Well, in general you will need different (although similar) models at least at these levels:
Server: here you can make use of Domain Driven Design. You will have an object Booking that is responsible for its logic and contain all properties and methods like e.g. MarkAsCancelled. You can use Entity Framework to use the same object in the database, which will correspond to a database table. EF allows you to mark some properties as not being saved in the DB. Also you can set up EF in the DbContext class and thus not use DB specific attributes in the class. So one object for DB and backend business logic.
API: obviously you cannot send your domain object to the API, e.g. REST. In the API you may want to combine properties of several domain objects or hide some properties. You will have to define a set of Data Transfer Objects (DTOs), e.g. BookingDto. How to convert your domain objects to DTOs? Solutions like AutoMapper may help. You just set up convertion rules once.
Now you can describe your API in e.g. Swagger. With Swagger Codegen you can than generate code for your server (.net) and client (e.g. JS).
In the end you will have to support the following:
API definition (e.g. Swagger). Code for server DTOs and client
objects is autogenerated. You modify API definition once, both sides
get new objects.
DDD Models that also are used for the Database. They
may be faily independent from your DTOs. Mapping is handled for you
semi-automatically by e.g. Automapper
All said is just a suggestion. All the layers and number of objects can and should be adapted to the specific needs of your project. E.g. you may want to use separate objects for the database if you are not using a relational mapper like EF or do not want to mix DB and logic.
My question might seem strange for pros but please take to account that I am coming from ruby on rails world =)
So, I am learning ASP.NET Core. And I like what I am seeing in it compared to rails. But there is always that but... Let me describe the theoretical problem.
Let's say I have a Product model. And there are over 9000 records in the database. It is obvious that I have to paginate them. I've read this article, but it seems to me that something is wrong here since the controller shouldn't use context directly. It has to use some repository (but that example might be provided in such a way only for simplicity).
So my question is: who should be responsible for pagination? Should it be the controller which will receive some queryable object from the repository and take only those records it needs? Or should it be my own business service which does the same? Or should the repository has a method like public IEnumerable<Product> ListProducts(int offset, int page)?
One Domain-Driven-Design solution to this problem is to use a Specification. The Specification design pattern describes a query in an object. So you might create a PagedProduct specification which would take in any necessary parameters (pageSize, pageNumber, filter). Then one of your repository methods (usually a List() overload) would accept an ISpecification and would be able to produce the expected result given the specification. There are several benefits to this approach. The specification has a name (as opposed to just a bunch of LINQ) that you can reason about and discuss. It can be unit tested in isolation to ensure correctness. And it can easily be reused if you need the same behavior (say on an MVC View action and a Web API action).
I cover the Specification pattern in the Pluralsight Design Patterns Library.
For first, I would like to remind you that all such examples you linked are overly simplified, so it shouldn't drive you to believe that that is the correct way. Simple things, with fewer abstraction layers are easier to oversee and understand (at least in the case of simple examples for beginners when the reader may not know where to look for what) and that's why they are presented like that.
Regarding the question: I would say none of the above. If I had to decide between them then I would say the service and/or the repository, but that depends on how you define your storage layer, etc.
"None of the above", then what? My preference is to implement an intermediary layer between the service layer and the Web UI layer. The service layer exposes manipulation functionality but for read operations, exposes the whole collection as an IQueryable, and not as an IEnumerable, so that you can utilize LINQ-to-whatever-storage.
Why am I doing this, many may ask. Because almost all the time you will use specialized viewmodels. To display the list of products on an admin page, for example, you would need to display values of columns in the products table, but you are very likely to need to display its category as well. Very rarely is it the case that you need data only from one table and by exposing the items as an IQueryable<T> you get the benefit of being able to do Selects like this:
public IEnumerable<ProductAdminTableViewModel> GetProducts(int page, int pageSize)
{
backingQueryable.Select(prod => new ProductAdminTableViewModel
{
Id = prod.Id,
Category = prod.Category.Name, // your provider will likely resolve this to a Join
Name = prod.Name
}).Skip((page - 1) * pageSize).Take(pageSize).ToList();
}
As commented, by using the backing store as an IQueryable you will be able to do projections before your query hits the DB and thus you can avoid any nasty Select N+1s.
The reason that this sits in an intermediary layer is simply you do not want to add references to your web project neither in your repo nor in your service layer (project) but because of this you cannot implement the viewmodel-specific queries in your service layer simply because the viewmodels cannot be resolved there. This implies that the viewmodels reside in this same project as well, and to this end, the MVC project only contains views, controllers and the ASP.NET MVC-related guttings of your app. I usually call this intermediate layer as 'SolutionName.Web.Core' and it references the service layer to be able to access the IQueryable<T>-returning method.
I'm not an ASP.NET programmer, but, as it happens in life, I had to do some minor projects using it. Now came another one in which I have to implement some custom solutions and I haven't figured it out yet - I need some tip or maybe a piece of advice like "don't go that way" ;)
Previously it was simple - there was a table in DB, there was an adequate model and a view that worked with it - worked like charm. Now it's a little bit more complicated.
The "site" is going to contain, shortly and generally speaking, a survey - but a fully configurable one, unfortunately. In another product there's gonna be a configuration manager that will allow user to define pages, block types, questions, steps and so on and will generate an XML.
For the time being, in accordance with the specification, in the site's database I'm going to have only one table which will contain just a key and the XML generated by the configurator (and maybe some additional, not important information). Now - I need to parse this XML and build the site containing pages and other elements corresponding to it.
And that WOULD not be a problem, but I don't really know how to work that way using asp.net + mvc and can't find any piece of advice that would help me anyhow. Should I create an object that would somehow fake being a model and allow me to work for example on a dataset generated from XML? Or just create a model of the mentioned table and work with the XML directly on the view (I don't like even such an idea itself)? Or - having to do something like that - just give up on MVC and use only "clear" ASP.NET? Or maybe something else?
I'll be very grateful for any help.
And I hope I described what I need understandably ;)
If the XML documents have a schema defined then you can easily generate a class that matches the document using the xsd.exe tool. The document can then be deserialized into an instance of that class using existing functionality in the .Net framework. Just google .Net Xml serialization :-)
Now, if you don't have a schema you could create one if you are sure that you know the format of the Xml. Alternatively you could create a class that matches the format you expect to get and then parse the Xml manually. This last option is much more work, so I wouldn't recommend it.
In any case, the class you end up with should contain all the data you need from the Xml document and can then be used as the Model in your MVC page. As long as you can use the standard Xml deserialization technique then this should be quite easy and painless.
In an ASP.NET application, we'd like to use the SqlWebEventProvider to log any Event that occurs during the application lifetime.
The problem is that we think that the table aspnet_WebEvent_Event doesn't provide enough columns and should log more information (we need to keep the Logged user).
I'm aware that this information could be stored in the "Details" column but it wouldn't then be really simple to filter the results and build reports.
So I'm searching for a simple solution to add a column. I wish I could derive SqlWebEventProvider but the methods used to build the stored procedure parameters are private (PrepareParams() and FillParams()).
Any simple solution that doesn't imply to rewrite the entire Provider class ?
Instead of adding columns to the SqlWebEventProvider and it's table default schema, you may consider creating your own WebEventProvider that logs events to a database of your own schema.
Here is an introductory reference on how to do so.
http://bit.ly/2fXeuH
After a lot of searching it seems that it is not possible without inheriting from the existing SqlWebEventProvider and overriding the methods properly to insert the values.
You can look into the .NET Framework code to check for the current implementation with .Net Reflector
I've got a person object with a name and age property that implements INotifyPropertyChanged. I want to hook this object up to an ASP.NET form so that the 'name' and 'age' properties bind to textboxes in a way that, when changes happen in either place (in the control or in the object) the other will get updated.
Do I create an intermediary class that listens to each textbox change events and the objects change events and handle the updates between them? What's the best way to do this?
I'm unclear on how to get business objects and the UI talking to each other.
I've stressed over this exact problem a lot.
The short answer is, yes, an intermediate item.
The trick is to NOT write ANY code per control. You should be able to place a GUI control on the screen (That may or may not take code), and then bind your business logic to it through a generic binding mechanism.
I have defined the bindings through XML, through properties files, and through constant arrays--there are a million ways...
You probably have to write code per TYPE of object bound (a listbox binds differently than a text control) and you may have to write validators (but specifying the parameters to the validators and which control the validators bind to should also be done in data)
Now all that said, I'd be really surprised if some data-driven auto-binding mechanism didn't already exist, Microsoft has been into that since VB first came out (although their implementations used to be pretty inflexible, I'm sure they do a better job now).
I'm very insistent about the 0 lines of code per control because my job has typically involved configuring complex devices with dozens of pages of controls. A typical client/server system will have 7(!) lines of code PER CONTROL just to transport data from the DB, to the server, to the client, to the screen and back (this is a minimum for plain ole "dumb" code with no smart binding tricks).
0LOC/control may not be a requirement for everyone, but it's a good goal.
Comment response:
I've done most of my stuff manually in Java, so I'm not sure I can be too much help with the specifics.
Searching for C# and binding gave me this which looks promising, although it may be binding straight to a database which is too much IMO, it should bind to a business object, but the concepts should be the same.
One way to create the bindings at first is to manually instantiate binding objects... (Please excuse my Java)
TextControl textCtrl1=new TextControl("Name Goes Here");
new TextBinder(textCtrl1, personObject, nameField);
In Java, that second line gets tricky. When you are binding to a particular field, you HAVE to use reflection to find the setter and getter for that field of the personObject. In C# I think it should be easier.
Anyway, the binder should add itself as a listener to the control and the object, then forward changes back and forth.
Does that help any?
Edit2:
As you noticed, the hard part is noticing when your property is updated. Luckily, that is optional. More often than not, you don't need to update the component once the object is set (I had to deal with this a few times when I had distributed UIs that could update each other).
So, if you assume your object won't change, the "Binding" has to do the following:
get the value from the property and set it in the component.
add itself as a listener to the component.
store the property/object (if you can manipulate properties, you're set here. If not, you need to store the object and property name, and use reflection)
bail and wait for an "updated" event from your component.
When you get the update from your component:
- store the value in the property.
- You may want to set an "Updated" flag or store the original so that if you iterate through all the binding components, you can tell if any updates need to be saved/enable the "ok" button.
Your object should always be pretty much up-to-date now.
As you build a form, you may want to put all your binding controls into a collection so that you can do a few other operations...
A "Save" operation could call each binding control and tell it to copy from the control to the property, that way you don't need to use a listener.
A "Reset" operation can reset all the controls to their original value.
A "Test" operation can ask each control if it's been updated.
. etc
The neat thing about doing it this way is that every "Operation" you wish to add is pretty trivial to add, but automatically affects the entire UI.
You probably also want a little object hierarchy of controls with an abstract base "bind" class, then a specific binder for each type of control (text field, number field, date, spinner, table, pulldown)--I think that's about it.
This can be very simple, but gains complexity rapidly. Try it with a text field and see what you can do. A simple text binding object should just be like 5 lines of code if you can pass "properties" around in C#...
Okay, totally separate answer. As I told you, I'm not very up-to-date with C# technologies, but from what I've heard, LINQ may do this entire job for you.
In fact, LINQ may be made to do exactly what you are trying to do. It doesn't exist in Java, so that's why I gave you the "Manual" version in the other answer.
The comment at the bottom of this page: http://msdn.microsoft.com/en-us/library/z919e8tw.aspx alludes to a better way.