Linq to Entities (join query) - WPF - 4 layer application - wpf

I'm new to this all and I like to know how experienced programmers handle the following situation
Let's say I have a table "Supplier" with some common fields and also fields MailingAddress, BillingAddress which are 2 key fields to link to another table "Address"
TB Supplier
Id = 1
Name = MyNameFoo
MailingAddressId = 100
BillingAddress = 101
TB Address
Id = 100
Street = MailingStreetFoo
City = MailingCityFoo
Id = 101
Street = BillingStreetFoo
City = BillingCityFoo
I have a 4 layer application solution:
project xyz.WPF which hold al my WPF windows to presentate the data to the user (Listbox with Binding)
project xyz.Business : in between WPF and DataAccess (SupplierB.vb, AddressB.vb)
project xyz.DataAccess.SqlServer : data layer (SupplierDAL.vb, AddressDAL.vb)
project xyz.Entities : to store my entity classes, each representing a table and just holding properties. I use this to pass from one layer to another (SupplierE.vb, AddressE.vb).
SupplierDAL class gets data from SQL Server and returns a "List(Of SupplierE)" to SupplierB class which return this "List(Of SupplierE)" to the WPF where it is bound to listbox -> Listbox.ItemsSource = SupplierB.GetAllSuppliers().
Now I can get all suppliers and show them in a WPF window in a listbox (or datagrid, ...) Also I can get all addresses and show them.
But at some point I want to get all the addresses (Mailing, Billing) for one Supplier. I know how to write my query with linq (join the 2 tables) but what do I have to do with the result of it. It is not a SupplierE nor a AddressE; it's a combination of the two. I want the result to be an object that I can pass around the layers, just like SupplierE.vb, AddressE.vb. Of course I could make another entity like SupplierAddressesE.vb; problem solved but in my real live solution I have dozens of join queries with joins between several different tables (not just Supplier, Address).
So a lot of tables, a lot of join query results; does this means I have to make a entity object (xxxE.vb) for each different join query or is there another way we can do this in a 4-tier layer application with Linq to Entities?
Thanks for any reply which can direct me to a good approach for this situation
Luc

If you are lazy loading the entities, then your supplier entity should have the attached address entity for each of Mailing/billing. Why not just have create a proper Supplier class that has properties for Mailing/Billing that are Address classes as opposed to Ids?

Related

How to run a stored procedure in EF/VB.net without knowing the type of the queries result?

My application uses a SQL Server database to store its data. The database administrator can create any queries in this database in the form of stored procedures with parameters.
These stored procedures in turn can be executed by my application. So, the users of my application can use these stored procedures without coming into direct contact with them. They enter the required parameters in my application, press a button, whereupon the query is executed (Entity Framework; Database.SqlQuery).
But all my application knows about these stored procedures is their name and their parameters.
The problem now is that I don't have a model for returning the data, since I don't even know what data columns the database administrator uses in his SELECT FROM statement.
Database.SqlQuery(Of Object) does not contain any data columns.
How can I display the data columns from a stored procedure in a grid, for example, without knowing the data columns themselves?
EDIT: it is a WPF application.
As others have commented, this situation isn't really ideal for EF, unless you're going to strike a deal with the DBA that they will always only return columns of a particular name and type (or some small variations) then you cannot effectively map them to objects, which have fixed properties. If you regard columns as properties, and properties as intrinsic to a kind of object then clearly these are different every day objects:
Name = "John"
Age = 23
Weight = 220
SocialSecurityNumber = "ABC123"
And
Manufacturer = "Ford"
Model = "Mustang"
EngineSize = "6.7"
VIN = "1234FM"
Can you guess what they are just by looking at the props (not the values)?
Sure, we could say "let's map them generically", we'll have one object and we'll mangle the properties into it
{
Maker = "Mom & Pop",
Model = "John",
GovtIdentifier = "ABC123",
Weight = 220
},
{
Maker = "Ford",
Model = "Mustang",
GovtIdentifier = "1234FM",
Weight = 4400
},
..but there isn't a really good way to refer to everything (EngineSize?), and you have to keep going adding more and more props, more and more of which will be null, if you can't reuse them..
All in, not EF's bag. EF wants entities, and every time you add one, thats a recompile and rerelease..
If the results will be wide ranging, and massively different in name/type from one query to the next, use a more dynamic container like a DataTable:
Dim dt As New DataTable
Using da as New SqlDataAdapter("some_proc_name", "some connection string here")
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.Parameters.AddWithValue("#a", "whatever")
da.Fill(dt);
End Using
myDataGrid.DataContext = dt
..so you assign it as the datacontext of a grid that autogenerates columns:
<DataGrid x:Name="myDataGrid" AutoGenerateColumns="True" ItemsSource="{Binding}">
</DataGrid>

How to retrieve a model and it's relationship as a single Array or Object | Eloquent, Eloquent: Relationships

i have 3 tables with one-to-one relationship. The phone table has one to one relationship with Model table and Model table has a one to one relationship with Manufacturer table.
phone_table
id
imei
image
model_id
model_table
id
name
image
manufracturer_id
manufracturer_table
id
name
logo
how to get a result like this :-
App\Phone{
imei : "356554512522148",
model : "Galaxy S-10",
manufracturer : "Samsung",
}
I would never throw it into the same array / object, i would firstly do that on transformation. If you use default Laravel transformation you can use getters for it. Simple example on how to access these fields into the same context would be.
$phone = Phone::with('model.manufactor')->find(1);
With secures the queries are optimal for accessing it. How to get data into same layer.
[
'imei' => $phone->imei,
'model' => $phone->model->name,
'manufactor' => $phone->model->manufactor->name,
]
For this to work, you need relations in your model too.
Phone.php
public function model()
{
return $this->belongsTo(Model::class);
}
Model.php
public function manufactor()
{
return $this->belongsTo(Manufactor::class);
}
Just join them:
\App\Phone::leftjoin('model_table AS mo', 'mo.id', '=','phone_table.model_id')
->leftjoin('manufracturer_table AS ma', 'ma.id', '='. 'mo.manufracturer_id')
->selectRaw('phone_table.imei, mo.name AS model, ma.name AS manufracturer')
->first()
And sometimes you need to think about why you want to split table to one-to-one relationship.
Is there a table not usually be used, or one of them need to be connected by another tables. is this just for saving space or reduce IO cost.
If there are not any other reason and you always need to get these tables' information, maybe you can merge to one table.

Two foreignkeys for one field in djangomodel

I'm having some trouble wrapping my head around this problem I've made for my self.
I have these two customer models, with some similar and some different fields. I want either of these two to be assigned as ForeignKey to a field in my projectclass.
The idea is, that when the user creates a project, the user can choose from all customers and assign from both private and company customers for that particular field, but not having to specifiy anywhere beforehand what kind of customer it is.
Private customer
class PrivateCustomer(models.Model):
.. fields
Company Customer
class CompanyCustomer(models.Model):
...
Project
class Project(models.Model):
customer = model.ForeignKey(PrivateCustomer,CompanyCustomer)
Can I make a join of the two for that particular field, on the fly, as instance occurs or should I just drop the seperation between the two customer classes and handle this through UI inputs?
How about having both fields with condition null = True
class Project(models.Model):
privateCustomer = models.ForeignKey(PrivateCustomer, null = True)
companyCustomer = models.ForeignKey(CompanyCustomer , null = True)
And then from your views, you can handle them easily.

Linq to Entities over WCF query help

Im using WCF data services to get my data from a Silverlight application, and I have a query of which I dont know how to write.
I have 2 tables, Resources and UnavailableResources they join on Resource.id and UnavailableResources.resource_id
the UnavailableResources table holds a record of a day that a resource is not available, so it is assumed that if there is no record in the table for a given date, the resource is available.
I would like to do a query for a date range (i.e. a given week) where for each day, I get all resources (if they are available or not), and, if they are unavailable, then get the status code (inside the UnavailableResources table which joins to a status table)
How can I do this?
From what I understood from your question:
var svcContext = new ServiceContext(svcURI);
var LeftJoin = from res in svcContext.Resources
join un_res in svcContext.UnavaialableResources
on res.id equals un_res.resource_id into joinedResources
from res in joinedResources.DefaultIfEmpty()
select new
{
// Properties you need
Status = GetStatus(isAvailable,res.id)
};
You can do more joins on the LeftJoin query to get what you want.
Let me know if I got your question right.

How to best represent items with variable # of attributes in a database?

Lets say you want to create a listing of widgets
The Widget Manufacturers all create widgets with different number and types of attributes. And the Widget sellers all have different preferences on what type and number of attributes they want to store in the database and display.
The problem here now is that each time you add in a new widget, it may have attributes on it that donot currently exist for any other widget, and currently you accomplish this by modifying the table and adding in a new column for that attribute and then modifying all forms and reports to reflect this change.
How do you go about creating a database which takes into account that attributes on a widget are fluid and can change from widget to widget.
Ideally the widget attributes should be something the user can define according to his/her preference and needs
I would have a table for widgets and one for widget attributes. For example:
Widgets
- Id
- Name
WidgetAttributes
- Id
- Name
Then, you would have another table which has what widgets have which attributes:
WidgetAttributeMap
- Id
- WidgetId
(a value from the Id column in the Widget table)
- WidgetAttributeId
(a value from the Id column in the WidgetAttribute table)
This way, you can add attributes to widgets by modifying rows in the WidgetAttributeMap table, not by modifying the structure of your widget table.
casperOne is showing the way, although I would personally add yet one more table for the attribute values, ending up with
Widgets
-WidgetID (pk)
-Name
WidgetAttributes
-AttributeID (pk)
-Name
WidgetHasAttribute
-WidgetID (pk)
-AttributeID (pk)
WidgetAttributeValues
-ValueID (pk)
-WidgetID
-AttributeID
-Value
In order to retrieve the results, you want to join the tables and perform an aggregate concatenation, so you can end up with data looking like (for example):
Name Properties
Widget1 Attr1:Value1;Attr2:Value2;...etc
Then you could split the Properties string in your Business Logic Layer and use as you wish.
A suggestion on how to join the data:
SELECT w.Name, wa.Name + ':' + wav.Value
FROM ((
Widgets w
INNER JOIN
WidgetHasAttribute wha
ON w.WidgetID = wha.WidgetID)
INNER JOIN WidgetAttributes wa
ON wha.AttributeID = wa.AttributeID)
INNER JOIN WidgetAttributeValues wav
ON (w.WidgetID = wav.WidgetID AND wa.AttributeID = wav.AttributeID)
You can read more on aggregate concatenation here.
As far as performance is concerned, it shouldn't be a problem as long as you make sure to index all columns that will be frequently read - that is
All the ID columns, as they will be compared in the join clauses
WidgetAttributes.Name and WidgetAttributeValues.Value, as they will be concatenated

Resources