I'm experimenting with XPO and attempting to wrapper some existing tables. Does anyone have experience with doing this? The problem I'm running into is determining how XPO determines the names of the linking fields for relationships.
For example, I have two tables,
Merchant( MerchantID, ProcessorID, etc...) linking 1 to 1 with Processor
Processor( ProcessorID, etc...) linking 1 to Many with Merchant
DevExpress says to set up the relationship as follows:
public class Merchant : XPLiteObject
{
[Association("Processor-Merchants")]
public Processor Processor;
}
public class Processor : XPLiteObject
{
[Association("Processor-Merchants", typeof(Merchant))]
public XPCollection Merchants {
get { return GetCollection("Merchants"); }
}
}
But my question is, how is XPO going to know which are the key fields linking these relationships together? This example compiles and runs in an XAP application, but the data is missing for each relationship (probably due to the fact it doesn't know which fields are linking the tables together).
Is there syntax I'm missing that I need to add to establish these relations? Or, maybe some extra code needed? The DevExpress documents say the above should work, but it doesn't.
Any help?
After experimenting with different syntax, I found that if I added the following to the Merchant class it works:
public class Merchant : XPLiteObject
{
[Persistent("ProcessorID")]
[Association("Processor-Merchants")]
public Processor Processor;
}
The PersistentAttribute can be used both for mapping classes to tables and for mapping properties to columns.
If you leave it out, the table-/columname will be the same as the class-/propertyname, and table/column will be created if missing. That's what happened at your first attempt.
http://documentation.devexpress.com/#XPO/clsDevExpressXpoPersistentAttributetopic
Related
With ServiceStack, I'm looking for ways to access related services by composing the URLs in a manner similar to OData.
An OData example would be a URL like
http://localhost:8080/owind.svc/Categories(2)/Products
This would find all the Products related to Category 2.
An equivalent example with ServiceStack seems to be that you would create a Request DTO for a ProductService and set up Routes something like this:
[Route("/Products")]
[Route("/Products/{Id}")]
[Route("/Categories/{Category}/Products")]
public class Products
{
public string Id { get; set; }
public string Category { get; set; }
}
(Ignore the separations of concerns issues mentioned here, the above attributes at least give a clear idea what I'm asking.)
And then in the ProductService you'd support finding Products either via the primary or foreign key. I see something along these lines used in the Northwind.ServiceModel.Operations.Orders class of the ServiceStack.Northwind.ServiceModel sample project.
So I'm wondering, is this the best and most scalable way that exists to do this sort of thing in ServiceStack, or is there some shortcut I'm missing? Thinking on a scale of creating services supporting hundreds of tables, if there existed some sort of shortcut, and if it didn't come with strings attached, it could be helpful.
I can imagine a system where you could automatically generate routes based on anything in a DTO, though you'd need to do some mapping from DTO property name (usually singular) to route (often plural).
No idea if it would be conceivable to carry this beyond one level either...for example
.../Employee/1/Orders/Customers
which would get you every Customer who has had an Order with Employee #1. The notion of implementing this manually on a large scale seems prohibitive. Not sure if there are SOA arguments to be made for or against, but that would be nice to know as well.
Just to be clear, there should be no assumption of the underlying data store or access libraries.
My system consists of a back-end part, written in Java, exposing a set of web services which are defined contract-first using WSDL and XSD. Among the data transported over the web services are a large set of product types (they are different kinds of bank accounts, to be precise). Our front-end is a Grails web application. It uses and exposes the data and operations hosted by the back-end. The front-end has no database on its own for security reasons; all data is stored on the back-end. Pretty standard architecture.
Now, the set of products is large, growing, and volatile. Each product type has to be CRUD-ed on the web application user interface. It would be lovely if I could tell Grails to use the XSD specifications of the product types as domain types, and generate views and controllers for them.
I have not found a solution for this puzzle yet, even after extensive experiments and lots of web browsing. I have about a year's worth of professional experience with Grails. Any help or ideas would be appreciated.
Some details:
A product type is a simple POJO data carrier. Some simplified examples:
package jaxbgenerated;
public class Product1 {
protected Account from;
protected Account to;
protected String name;
// + getters and setters
}
public class Product2 {
protected List<Account> accounts;
protected String name;
// + getters and setters
}
public class Account {
protected String id1;
protected String id2;
// + getters and setters
}
Note that "Account" is not a product type but it is a JAXB-generated type. Products can contain such in addition to properties of simple data types like String, int and Date but they never contain other product types.
The end result I am aiming for is a Grails-generated form where a user can edit a Product1 instance with nested forms for editing its constituent Accounts. And likewise for Product2.
My idea is to first manually code a Grails domain class for each JAXB-generated type:
//in grails-app/domain:
import utilities.Copier
class Product1 extends jaxbgenerated.Product1 {
Product1(jaxbgenerated.Product1 jaxb) {
Copier.copy(jaxb, this)
}
static constraints = {
}
}
There is a bit of boilerplate code here but nothing more than I can live with. The Copier.copy() function is (I think) needed to convert a jaxbegenerated.Product instance fetched from the back-end to a Product1 instance which can be used in Grails. It recursively looks for jaxbgenerated properties in the jaxb source, and copies their values to the corresponding Grails domain type. The constructor is invoked from a layer that fetches data from the back-end.
I can use the constraints block to manually add semantic constraints where needed, e.g. that the "from" and "to" accounts are not the same.
Next, I generate controllers and views for all the Grails domain classes thus constructed, and run the application. And get a stack of exceptions:
Caused by MappingException: Could not determine type for: Account, at table:
product1_type, for columns: [org.hibernate.mapping.Column(from)]
I think the trouble here is that Product1's "from" and "to" properties are not of type Account but of type jaxbgenerated.Account.
I have tried different approaches but to no avail. Some notes:
As I said, all data storage happens on my back-end, so I do not need
the GORM/Hibernate aspect of Grails. Therefore I tried adding
"static mapWith = "none" to the domain classes but that did not
help.
I tried explicitly telling Hibernate the type of the Accounts
in Product1 by adding "static mapping = { from type: Account }" but
that did not work either.
Any help or ideas would be appreciated.
/Jan Reher, Systematic A/S, Denmark
I think you have do write a dababase plugin similar in concept to this simpledb
I have a set of fields that I intend to share between multiple models. I want all the fields to be included in each entity's table (not just one table for the fields). I'm more familiar with languages such as Python, where this type of pattern is called a "mixin", essentially a class that doesn't exist on its own (it doesn't get instantiated/doesn't have a table in the case of a model class). Instead, the derived class simply inherits the fields and its table looks as if the fields were simply included right on the model class.
The concept of a "Complex Type" in Entity Framework seems like a close proxy to what I'm looking for, but the inability to include navigation properties is a bit of killer. Is there any other way to do this, or if Complex Types are the answer, then what should I do about the navigation properties?
I've read this note in a book:
An interesting possibility beyond base classes and interfaces are mixins, but they are an OOP feature not supported by .NET languages. A mixin is a class that provides a certain functionality that other classes can inherit, but it is not meant to be a standalone class. Put another way, a mixin is like an interface where some of the members might contain a predefined implementation. Mixins are supported in some dynamic languages, including Python and Ruby. No .NET languages currently support mixins, but mixins can be simulated using ad hoc frameworks such as Castle. DynamicProxy. With this framework, you first define a class that contains all the methods you want to inject in an existing class—the mixin. Next, you use the framework to create a proxy for a given class that contains the injected methods. Castle.DynamicProxy uses Reflection.Emit internally to do the trick.
You can do this using inheritance. If you've already considered that, I apologize. Code follows.
public abstract class WidgetBase
{
public string Name { get; set; }
}
public class SweetWidget : WidgetBase
{
public int SweetnessFactor { get; set; }
}
public class SourWidget : WidgetBase
{
public int Sourness { get; set; }
}
Then in your model configuration, you do:
const string discriminator = "WidgetType";
Map<SweetWidget>(mc => mc.Requires(discriminator).HasValue("Sweet"));
Map<SourWidget>(mc => mc.Requires(discriminator).HasValue("Sour"));
You will need to add a column, "WidgetType", to your table. EF will then populate it as specified in the mapping.
Note that the base class MUST be abstract. As long as your table contains all of the fields for all of the derived classes, this is how you do Table Per Hierarchy in EF Code First.
Actually had a chance to discuss this with one of the developers on Entity Framework. It's not technically possible at this time. It's apparently being kicked around, but no one is working on it at this point. Complex Types are a sort-of version, but they of course don't support navigation properties. Thanks to everyone who took at stab at it for me.
I've created a one table contact DB, which has only 3 columns (Id, Name, and Phone). I've then created the ContactsDataContext using my table Contacts in the model folder. Finally, I create a partial class still in the model folder (public partial class Contact).
now when I write this
public partial class Contact
{
public string MyContact
{
get
{
string name = this.Name ?? String.Empty;
}
// ... Other lines omitted
}
}
I get the following error :"'ContactsManager.Models.Contact' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'ContactsManager.Models.Contact' could be found (are you missing a using directive or an assembly reference?)"
Is something wrong??? Even the Intellisense in not showing the properties from my DataContext class. Yet, I've written some partial classes in the past with no problem.
Thank you.
Are namespaces the same on the two partials?
Chris Roden,
Yes, I've resolve it. In fact, I've asked the above question many months ago when I started learning ASP.NET MVC. I bought a book called "ASP.NET MVC - The Beer House/Nick Berardi/Wrox." Is a god book, but it's not recommendable for beginners. Generaly, things are thrown like that without telling where they come from.
The response came from applying the definition of a partial class. Among others, partial classes must:
have the same name
be preceded by 'partial' keyword,
be defined in the same namespace,
etc.
If you miss any of the above criteria, then you'll be in trouble because those criteria, ll be used to merge all the partial classes into a unique one.
In my case, I created a table called ContactDB. After I've created the datacontext class, I've dropped the ContactDB table on the Linq2Sql editor. As you must know, that creates the following class:
public partial class ContactDB
{
//All the columns in the table become properties in this class
}
The partial keyword allow me to write this:
public partial class ContactDB
{
//I can reference members of the above partial class... using this keyword
//After all, the 2 constitute one class.
}
After reading the definition of partial classes, I found out that I failed one of the criteria. I called my other partial class "Contact" which's different from ContactDB. That was enough to make me go crazy for 3 days until I read the definition. Moreover, if you defines the partial class with the right name but you put it in a different namespace, you'll get in trouble as well.
So, if the above answer doesn't work for you (I don't know exactly your problem), check the definition of the partial class.Don't forget to read the ScottGu's series on Linq2Sql.
Hope it helps.
Ok, so let me explain a little of what I am trying to do.
I have a table called WebsitePage that contains all of the pages on my site with some information about them. Then, I have a Customer table for all of my customers. Then I have another table called CustomerWebsitePage that stores customer values for some of the columns in the WebsitePage table.
So, using the entity framework, I imported these three tables. What I want to be able to do is return a strongly typed WebsitePage list that has any values from CustomerWebsitePage if there are any values for it. So, for example, say one of my customers added a CustomerWebsitePageName for one of my website pages. I want to return a list of WebsitePages that contains the CustomerWebsitePageName instead of the WebsitePage Name in that case. But the original WebsitePage Name for everything else since it wasn't overridden.
The kicker here is that my WebsitePage table has a foreign key to itself for a Parent/Child relationship. So, I also want to return the child WebsitePages at the same time. I tried using a function import to get what I wanted, but then of course I lost the ChildPages.
I have tried just about everything to get what I want using the Entity framework and LINQ. But so far almost everything I try ends up with an exception being thrown. Here are a few:
The EntityCollection has already been initialized
The entity or complex type 'MyEntityModel.WebsitePage' cannot be constructed in a LINQ to Entities query.
I have one idea of how I can get around all this, and that would be to duplicate the ParentPageID into my WebsitePage table, but this really seems to violate a lot of principles and I really just don't want to add the maintenance headache related to this.
Anyone have any ideas how to accomplish this type of thing?
A simple DB diagram. http://images.tehone.com/screenshots/2009-08-17_013009.png
The object that you need to return is a CustomerWebsitePage and not a WebsitePage. The reason is that whatever object you return must know about the customer since the property will need it to determine which field (CustomerPage or WebsitePage) to use.
Considering that, you can have a function CustomerWebsitePage.GetAllPagesForCustomer(Customer c) that would return an enumeration of pages. However, to achieve the functionality you are looking for, you must implement some read-through properties in the CustomerWebsitePage. Let's take the example of Name. Here would be how to implement it in CustomerWebsitePage:
public string Name
{
get{ if( String.IsNullOrEmpty(CustomerWebsitePageName) )
return WebsitePage.Name;
return CustomerWebsitePageName; }
}
For the Children pages, you could have a property:
public IEnumerable<CustomerWebPage> Children
{
get
{
return WebsitePage.Children.Select( it => it.Customer.CustomerID == this.CustomerID ); }
}
Note that with this setup you couldn't run EF Linq queries on these new fields (because they exist only in the objects themselves, not in the database mapping). You can pepper the code with Load() if you want to seamlessly load all the children, but it will cost you in performance. To ensure that all the children are loaded, try the following loading function:
IEnumerable<CusomterWebPage> GetAllPagesForCustomer(Customer c)
{
return Context.CustomerWebPageSet.Include("WebsitePage").Where( it => it.Customer.CustomerID == c.CustomerID );
}