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

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.

Related

ER model generation generates two properties for foreign key

I am learning MVC and I'm creating a project in which I'm Display Information like GSMarena.com phone description. I have created separate tables for Technology, Design, Display. I have used their Primary Key as Foreign key in Products Table but when I generate model in edmx file it creates properties like Design, Design1, Display, Display1 like shown in figure. I'm not able to get the reason behind this as on product create view I need all these properties for product creation.
Why is this happening and how it will effect my project?
With respect to your comment
...when I generate model in edmx file it creates properties like
Design, Design1,...
The Design1 property is the actual table. This means that from the Product table you can access the fields of the related Design table, for example you could type myProduct.Design1.Dimensions to access the Dimensions field from an instance of Products.
The Design property is the actual numeric value of the column Id of the Design table.
I hope this is clear enough.
In the top part of you Product model, you've created fields for Brand, Camera, Connectivity, Design, Display, Hardware and Technology. These are not Foreign Keys
So when you add the associations between the classes, it adds Navigation Properties (which are Foreign Keys) to the table, with the next most appropriate name.
Just remove the fields from the top half of the model and rename the Navigation Properties.

XAF/XPO How to integrate legacy database

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.

C# EF4.0 POCO - how to set navigation proprety with entity from different DbContext?

I want to set a foreign key on an entity. I have the foreign entity exposed in my user control, and want to set it via WinForms data binding.
Here's the catch - the foreign entity was originally loaded from another repository/DbContext, as the user control populates itself independently using its own repository.
Unfortunately this doesn't work "out of the box", as this example demonstrates:
var repository1 = GetRepository();
var categoryFromRepository1 = repository1.GetAll<Category>().First();
var repository2 = GetRepository();
var appointmentFromRepository2 = repository2.GetNewAppointment();
appointmentFromRepository2 .Category = categoryFromRepository1;
repository2.Add(appointmentFromRepository2);
repository2.SaveChanges();
This fails on at Add() with the following error:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
OK, so repository2 can't auto-attach the Category because it's attached to repository1. Great, so let's detach first:
repository1.Detach(categoryFromRepository1);
Which fails on SaveChanges() due to a validation error - whoops, turns out repository2 thinks it's an Added entry and trying to insert. Great, so let's attach as well to avoid this:
repository2.Attach(categoryFromRepository1);
And this works! Problem solved. I've now set the repository2-entity property to the repository1-entity, voila.
Except that this solution sucks swamp water... We have many data-bound self-populating user controls throughout the program, and manually detaching/reattaching all the foreign entity references prior to SaveChanges() is a horrible solution. Furthermore, supposing the repository we're saving via happens to have the object attached already then we get this error when we Attach():
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
None of the solutions I can think of are that great:
1) In our generic repository class on SaveChanges(), scan all foreign references on all modified entities for out-of-DbContext entity references, dynamically change them to the in-DbContext entity reference (load from DB if necessary)
2) Don't set the navigation property at all, just set the foreign key ID field (sucks0rz yo' b0x0rz)
3) Manually do these checks before save (violates DRY & persistence-ignorance principles)
4) Abandon data-binding to these properties, manually set properties & load entities from the main repository (terrible - means extra queries to the database for data we already have)
5) Fudge user controls so that they can load their data from a given repository, if required (poor solution, violates some basic design principle... but workable)
Any other ideas, plz?
Regards,
-Brendan
Given the presence of multiple DbContext instances, it seems you have multiple bounded contexts at play. Specifically, there are multiple aggregates at play, namely Category and Appointment. Due to issues such as the one you're having, it is desirable to implement references between aggregates using only the identity value - no direct object references. If Appointment references Category by ID alone, you wouldn't have this problem. It is likely though that you need the entire Category aggregate for display purposes. This requirement can be addressed with the use of the read-model pattern.
Take a look at Effective Aggregate Design for more on this.

Should the properties in Data Transfer Object expand the foreign keys or simply expose their primary keys

I have an EmployeeDTO that respresents an Employee record in the database. The Employee table has a relationship to a Department and a 1-to-many relationship to Permission.
In my entities, these are represented as a fully expanded Department property and a List of fully expanded permission objects.
The question is should the DTO have a fully expanded DepartmentDTO property of a DepartmentId? Should the DTO have a list of fully expanded PermissionDTO properties of List of PermissionId?
Just like everything in design, it depends on your needs.
If you need to frequently see and
bind to child properties and you want
to make it as easy as possible for
developers to use your DTOs, you may
want explicit factory methods to give
you fully expanded child properties.
If you want simplicity of code, don't
expand the foreign key properties and
just let developers get the child
object/collections they want by key
as needed.
You may run into problems in recursion; do you also expand all the foreign-key properties of the Department object too? What if there is a reference to another EmployeeDTO in a subclass of Department?
Microsoft's Entity Framework, as well as other popular business object frameworks, handle this concept by lazy loading -- only fetch the full expanded child property if it is called for by the code. This is probably the most flexible solution, but has a little overhead/lag as child properties can't be fetched in the same database call as the parent object. These are of course not purely DTOs.
Yes and No. It depends on the call and if you would need all extra properties in every call. It can also depends on the ORM technology you use which can implement lazy loading and can affect your decision (if you are passing straight entity objects although it is not recommended).
It is common to create one case DTO containing all necessary properties and one or more DTO object that expose more functionality and are used it other methods. For example, I have a BasicUser class which only contains UserName and DisplayName and I have User which contains more including Permissions and inherits from `BasicUser.

Where does the 'Name' property in a DBML come from?

I'm using Linq-To-Sql and inside my DBML there are objects built from the database connection provided.
If you click on an association line between two tables and view the properties on it, you will get the following:
Cardinality
Child Property
Access
Inheritance Modifier
Name
Parent Property
Access
Inheritance Modifier
Name
Participating Properties
Unique
My question is, where does Linq-To-Sql get the "Name" properties from? Where is the correlation to the actual database?
I ask this because if this table happens to be a parent to several children, Linq-To-Sql will just simply name these properties, "SomeParentName", "SomeParentName2", "SomeParentName3" , etc. So you'd have to go into the DBML and manually change these names to something meaningful every time you update this table.
Any help you can provide would be appreciated.
Part 2 of my question might be how do you guys handle these situations?
As for the Name: It takes the child / parent and comes up with something based on some internal voodoo. Don't ask me how.
As for Part 2: If you tend to have to redo stuff every time you update something I STRONGLY suggest switching to Entity Framework. It's very similar, but you can just hit "update" and your modifications are kept.

Categories