XAF/XPO How to integrate legacy database - c#

We are experimenting with DevExpress XAF & XPO in order to use it for our further devlopment of an existing small business ERP system. We have a SQL database, where the existing tables must not be changed. What we are trying to do is to add new needed table properties only to a new tables that then should be "connected" to the old tables through object inheritance (MapInheritanceType.OwnTable).
For example:
We have a legacy tCustomer table. Now we add an XPO object tCustomerExtended like
public class tCustomerExtended : test.Module.BusinessObjects.db.tCustomer ...
The tCustomerExtended class then shall be extended with new properties and the tCustomer class remains unchanged (in order to be used by the old client application).
This works fine of course. A new table tCustomerExtended is generated with a primary key kCustomer (the key of the legacy table). Also XAF generates a UI as expected: The tCustomerExtended view is empty, since it shows the tCustomerExtended entries.
!!! But what we really want to achieve is to show all existing tCustomer entries in this view and the new properties of tCustomerExtended. The OnSaving method should then save the legacy properties to tCustomer and the new properties to tCustomerExtended. Also we have to generate a kCustomer key, since the old tCustomer table kCustomer PK has no Identity Specification.
At this moment I do not realize how to achieve this without changing the old tCustomer (what is absolutely not allowed).

By default, when you create the subclass tCustomerExtended, XAF should generate detail views which include all the tCustomer properties too. I'm not sure why you are not seeing that behaviour.
Can't just add new columns to your old tCustomer table. So long as you don't change any existing columns, your old system should continue to work. Does your old system break if there are extra columns in the tCustomer table? If only minimal changes are allowed, you can just create an [Aggregated] property with [ExpandObjectMembers]. This will add a single column to the old tCustomers table which will provide the link to all the extended properties.
If you really do need two tables with zero changes to tCustomer, then I think you will need to jump through some hoops to achieve exactly what you want. It's certainly possible, but the best answer will come from the the DevExpress support center (as for all DevExpress-related questions). If you post a sample project there, the DevExpress team will quickly provide you with the best approach for your situation.

Related

How to implement LinkedList in Entity Framework Core

I want to persist a linked list of objects using in my ASP.Net Core application. For simplicity, I'll use blog and comments; although the real context is much more complex.
I scaffolded two tables, and changed ICollection<Comment> to LinkedList<Comment>. However, if I create an initial migration and apply to an empty database, I don't get anything "linked" in the database (no next or previous). Also, if I seed the data, and then do something like this:
var comments = _context.blogs.First().Comments
I get null. If I leave public virtual ICollection<Comment> Comments, I get the IEnumerable just fine.
I tried to use LinkedList<LinkedListNode<Comment>> instead, and it works nice unless I try to create a migration. Getting an error
No suitable constructor found for entity type 'LinkedListNode'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'value' in 'LinkedListNode(Comment value)'; cannot bind 'list', 'value' in 'LinkedListNode(LinkedList list, Comment value)'.
I couldn't find any guidance how to implement LinkedList in C#/.NET Core (obviously, I can do it manually, having next and prev fields - but I would very much prefer to use framework capabilities, if possible!)
I don't know much about MS SQL server, but the whole next and prev parts in mysql won't work because you can't map the keys it would require to track the fields properly because each link has to have an id in a database to link to. only thing I know of would be create the next/prev yourself and use some custom data persistence or data annotations. but the foreign key constraints I'm pretty sure on any relational database will prevent you from auto persisting those types of fields. reason being tracking deletes, inserts etc would be a nightmare because if you remove the middle of the chain, then the database has to try and guess where to link the ends to

Oracle View base on a PIVOT query not null values

When creating a View based on a PIVOT query all the view fields become NULLABLE in the view metadata, is there any way to make them NOT NULLABLE?
I'm using the NVL function in the pivoted fields I need to be NOT NULL but they still become NULLABLE.
This is a problem to me because I'm using MS Entity Framework and it won't update the model based on tables or views without NOT NULLABLE columns.
#Miguel, I don't know the "MS Entity Framework" but the name makes it sound like a framework that is oriented towards editing data. 'Entity' is typically used for structuring a cache of database data in preparation for changing and updating that data back into the database. This does not seem like what you want to do.
Re-reading this question I believe that you have some sort of pivot generator you are using to create the view on-the-fly for the user. For this reason you do not intend to revise the Entity Model. I don't think you need an entity model at all.
An Entity Framework is likely to be looking for NOT NULL columns in order to find a 'primary key' or other row-level identifier that it can use. Why does it want these?
provide a key usable to update any row
provide key for paginating the result set
provide a key to support in-memory filtering of the result set
support dynamic sorting operations on the result set
I also surmise you have some sort of UI control that presents 'Entity' collections very nicely and so you want to use that control.
The control may not need an 'Entity' - check to see what its interface is. Perhaps there is a superclass of Entity or an interface that you can generate rather than an updateable Entity. If you can do that, you should be able to present it in the spiffy UI control and not hit the wall with your NULLABLE columns.
One of possible solutions is generating a new table on the fly based on results of query and tuning constraints for this table after that.
I don't like this method for too many dynamic SQL :)
Another solution is a prebuilt materialized view.
Look here (Oracle docs) for "ON PREBUILT TABLE Clause".
You need to update your model in Visual Studio (VS). Because this doesn't know what type information is in every column. Then you have to specify in the query of pivot table the data type. For example, Use to_number for specify a explicit conversion. When you going to update the model in VS you must based in for example materialized view (with explicitly defined data types). Please create Materialized view with explicitly defined data types based in the pivot table (this have to contain not only nvl function else defined data types, string, number, etc ) and then Update your model.
Only Materialized view? No, it can be a table (but is troublesome). Can be It direct of the pivot table? Does not always work (as in your case). Important Is to have defined data types.
You could use code-first if you don't have to many of these views, Scott Gu has a good article "Code first with existing database" that shows how to do this.
This might entail having 2 ways to access the db, which may or may not work for you.

How can I denormalize my clr entity, but keep my db tables normalized?

I have these two related tables Client (ClientId, Name) and ClientDescription (ClientDescriptionId, (FK) ClientId, Description). That is to say each Client can have many associated descriptions. Now, when displaying the a list of ClientDescriptions, I also need to know what the Name of it's associated Client is.
Now you'll probably say that I allready have this information, since I can simply follow my navigation property back to the associated Client and use its Name. I can't do that because I'm autogenerating a grid in Ria services, and this just gives me a count for navigation properties, and I haven't found a way to flatten this down in my metadata file. Hence why I want a property.
The whole idea is that I want to be able to add a new field to my database, update my entity classes from the database and regenerate my domain service, and the new field should just pop up in my grid. I shouldn't have to update my xaml just because my database happen to have an extra field.
So, what I would like to do is add a ClientName field to the entity (clr object), but keep my database clean (no such denormalization in the db).
So, I generated my edmx, and added a new property named ClientName. Set it to StoreGeneratedPattern.Computed, and compiled. I then get a nasty little error
Error 3004: Problem in mapping fragments starting at line NN: No mapping specified for properties (etc..)
The solution apparently is to generate my database from my edmx. (Or that's what answers to questions about that error seems to yield.) But this generates an actual DB-field, which I don't want, so that answer doesn't apply to my case.
So my question is: How can I denormalize my clr entity, but keep my db tables normalized?
Edit: I guess this question can be generalized a bit. The issue would be the same if ClientDescription contained a few numeric fields that I wanted to do some calculations on, and I wanted the result available as a field and the algorithm should be in c# rather than in my database.
To answer your more generalized question:
Entities are generated by the Entity Framework with a partial keyword.
This means that the code of an entity can be split in multiple source files in the same namespace and assembly. One will contain the generated code from the Entity Framework, the other will contain custom properties and methods.
If for example, your entity has the database fields Price and Amount you could add a property in the partial class TotalPrice which would return Price * Amount.
Then the algorithm will be C# and your database won't know about the extra property.

Entity Framework - Track changes and rollback

At the moment I've got a big Entity Data Model (.edmx) with a database underneath it. Now I want to give people who use my site the option to edit those entities but only after I gave approval of the change.
So this would mean that I want to "change" the entity but not really save it yet, after I accepted the change it would override the enity with the changed one. But when I did this I would still like to be able to rollback the change afterwards.
Now I've come up with a few solutions:
1) Make a entity with like: [ID], [ChangeApplyDate] [ChangeApproveDate] [Entity before change] [Entity after change] [Accepted (boolean)]
2) Make an extra entity with the changed values and a link to the "Original" entity and have a boolean in this entity if it is the current approved one or not. (this would not create a new table but expand the table like, "Book", with a few extra properties.
Now I would like to know how you think about those solutions and if you ever made something like this?
There are two things here:
Keep a list of all previous versions. Have a look at my answer to this question: Ideas on database design for capturing audit trails
Controll the acceptance of changes. To do this you could add an approval flag to each table, which only you have access to.

decoupled generic key-value access against linq in a non-xml environment

good morning.
i am not a computer scientist by education, so please overlook any shady term abuse.
in my framework, a base form called Record opens form RecordDetail as dialog. for example, RecordClient extends Record and contains client data and tabbed lists of client-relevant child data, and RecordDetail expands one child data row for detailed editing based wholly on reflection and display overrides stored as custom attributes used against DataContext. Record is subclassed for the application, but i see no need to subclass RecordDetail. this works except for the display of foreign key edits in the listed children.
i must use ObjectListView and Linq; i cannot use WPF/XML. because i do the serialization trick for non-continuous database connectivity, i lose foreign key objects when i clone data to manage state. ObjectListView needs the foreign key object for display and general wickedness. i know Hibernate, but Linq leaves me at a loss:
how might i access the foreign key object from within Record after its dialog to RecordDetail closes - without coupling framework and application-specific classes?
that is,
Type rowType = row.GetType();
IDomain workDamnit = (IDomain)dataContextReflectedFromRowType.GetTable(rowType).Where(x => x.PrimaryKey == 1).SingleOrDefault();
where "PrimaryKey" wraps the primary key attribute, and the fail happens between "GetTable", "Where" and "SingleOrDefault".
any perspective appreciated on this fine sunday morning.
actually, i've decided to uncle under and cache the foreign key objects in a pool accessed by the subclassed Record forms.

Categories