Business Objects/Custom Classes DAL Design - asp.net

I need some advice on how to handle this scenario. My application has many tables and custom classes mapped to those tables. Let's use the following as an example (pseudo-code):
Public Class Country
Name As String
Language As String
Capital As String
President As String
Public Class State
Name As String
Capital As String
Country As String
Public Class City
Name As String
State As String
Country As String
Retrieving an individual object of any of these classes is straight forward. Retrieving lists of any of these objects is straight forward as well.
Where I need guidance is how to retrieve a combination of these objects. For example we may need to display a list of City Names and Country Presidents (excludes the State Class). What object should I use to hold that data? I want to avoid retrieving the State data because trips to the database are expensive. I typically present the information using repeaters so I also need an object that is easily bindable to a repeater.
Thanks for your help.

Related

Problem with one controller handling two forms (models)

I have to implement this form, which at first seemed easy to me. For the models part, I created a one-to-many relationship between GeneralInformation and CourseList (very obvious). In the GeneralInformation I included the bottom section as well with the 'Comments', 'Remarks'etc.
The problem is that before submitting the General Information section, you fill the Course List which will give an error for the FK constraint (again, obvious). For the Course List I'm using DevExtreme datagrid.
The only solution I came up with is to create another table, which keeps the ID of GeneralInformation and each Course ID. A similar solution for many-to-many relationships. If this seems like a viable solution, then how do you store the IDs of Courses in the controller, and then the ID of GeneralInformation, to put them in the database. Now I think I'm handling two models with the same controller, which might not be an optimal solution or even against guidelines of .NET Core.
If someone has a better solution, it would be greatly appreciated.
Your Model can be like this
public class Model_Name //enter your model name
{
public string FirstName {get;set;}
public string LastName {get;set;}
//other properties from General Information form
public List<Course> Courses {get;set;} //Course is a separate model
public string Remarks {get;set;}
}
In HTML do not map course to General info, Post the form and pass all the fields as json like below
{'FirstName':'Test','LastName':'Test','Courses':[{'Id':1}], 'Remarks':'test'}
So you're basically asking how to bind to a collection in a model.
Property binding would look like this:
<input asp-for="#Model.Collection[i].Property" />
What i did was store the course table (or grid) row as a partial view that takes an index as an argument with the course model and at the same time i maintain an index of the courses count using data-id attribute on each row and then every time a user wants to add a course i use ajax with the index of the last course as a parameter to fetch a new row rendered with an incremented index
and i append it to the table.
That way when your submit your form it will bind to a collection what ever the length is.

Writing DTO Class to build object getting informations from different Data Sources

I'm following Domain Driven Design for this project.
I have got an object containing an image. Let's call it Product:
class Product {
UniqueID id;
ProductName name;
ImageBytes imageBytes;
}
UniqueID, ProductName and ImageBytes are just validated objects that represent respectively a String, a String and a List<int>.
I would like to store the actual image on Firebase Storage and saving the imageId on Firestore.
So, in my idea, I have an image on Firebase Storage with id xYF87Ejid0093RTcxaWpof and a Doc in the Firestore containing this id instead of the actual image.
The problem I'm stuck into is writing the Data Transfer Object of a Product. How should I convert an imageId into the actual image?
Please consider that I'm using DDD, so my DTO and my Entity classes are Unions (using Freezed).
I think I should have an intermediate class called FirestoreProduct at the Infrastructure level that looks like this:
class FirestoreProduct {
UniqueID id;
ProductName name;
UniqueID imageId;
}
So that I can write a DTO that uses this class instead and I can create the Product object from the repository class after I downloaded the image.
Is there any better way to solve this problem in the DDD way?
Thanks in advance.
Do you really need the ImageBytes to perform the business logic of your product entity? I even guess that your Product is an aggregate root and thus will have data and corresponding behaviour (business logic) in it.
So from my point-of-view the model of your FirestoreProduct is closer to a domain model than your Product class.
I consider your image a separate aggregate which can reside in the same service but a different storage or which could even live in a separate service.
Either way the Product aggregate should only need a reference to the image. I would model it somehow like this
class Product {
ProductId id;
ProductName name;
ImageId imageId;
}
whereas ProductId and ImageId would be value objects for strongly-typed ids.
I expect the storing/upload of a new image to be performed in a separate transaction than creating/updating a product itself. That means when you create a new product or perform some business logic on it to change it your image has already been uploaded to the Firestore and you only work with the image id in your product aggregate.
Your Product DTO (you could also call it view model) on the other hand which you use for providing data for the UI (i.e. for reading data) can look different then the Product aggregate. This is okay and also makes total sense.
So the DTO would look something like this instead:
class ProductDto {
UniqueID id;
ProductName name;
ImageBytes imageBytes;
}
Note: I don't know if ImageBytes is the right type for the DTO as my flutter knowledge is limited but I hope you get the idea.
With that you can bypass the Product aggregate domain repository completely and have another service class which will give you all the data you need for reading/viewing the Product data. As you do not change anything by reading data you do not go through your domain model and optimize for reads.
The code which than builds the DTO will go to your persistence for querying some Product data but also to Firebase for querying the actual image. You could even reload the actual Firebase image afterwards by a separate call from the UI if performance is an issue, for instance if you retrieve a whole list of product data for reading at once.

How can I inherit using TPT using EntityFramework from different Views?

Supposing I have two tables Meetings and Attendees.
My database looks like this.
// Table Meeting
Id
Description
// other properties ...
// Attendee
Id
Name
MeetingId
// other properties ...
I have two views that are mapped to these tables. One is ViewMeetings with just the meeting data the other ViewMeetingAttendees joined with Attendees.
I want to use table per type(TPT), mapping each table to a view.
public abstract class MeetingBase
{
// Some properties here
}
public class ViewMeeting : MeetingBase
{
}
public class ViewMeetingAttendee : MeetingBase
{
public String AttendeeName { get;set; }
}
// Configuration
moduleBuilder.Entity<ViewMeeting>().ToTable("ViewMeetings");
moduleBuilder.Entity<ViewMeetingAttendee>().ToTable("ViewMeetingAttendees");
// NOTE fixed the ViewMeeting error as stated in HansVG answer below.
Every time I try to run this code I get an error Invalid Column Name "Discriminator"
I understand that the entity framework is trying to resolve the types as a table per hierarchy(TPH). However, I still want to map the properties using inheritance without the inferred TPH. This is reasonable since all the columns are the same except for one. I have ten other columns and two views. Also I have a single meeting entity needing most of the same columns for CRUD operations.
Is there a way to keep the inheritance but lose the discriminator error? [NotMapped] is not an option since I am still pulling the data from the database. Also, I don't prefer to join the tables locally using LINQ since there are joined entities that don't need to be mapped otherwise.
You defined 'ViewMeeting' twice and didn't configure 'ViewMeetingAttendee'.
Your configuration should be:
moduleBuilder.Entity<ViewMeeting>().ToTable("ViewMeetings");
moduleBuilder.Entity<ViewMeetingAttendee>().ToTable("ViewMeetingAttendees");

Enum for common names in Request.Form collection

Does ASP.NET contains any enumerator for common field names used in Request.Form collection such as "_EVENTTARGET" and "_EVENTARGUMENT"? I need to refer to those names in multiple places in my app and I would love to be able to type something like this.Page.Request[CommonRequestNames.EventTarget] instead of hard-coding them.
There is nothing like this built into the BCL.
Instead of an enum consider using a set of public constant strings.
The reason enums are a poor choice is that they can only be based on integral types (except Char), not strings and you would end up having to translate from enum value to enum name and back, which can get messy.

ASP.NET MVC2 - specific fields in form pass via a specific object?

In database I have Contacts table:
ContactID (int)
FirstName (varchar)
LastName (varchar)
...
XmlFields (xml) // This field is xml type
To create a new contact, I created two classes - one for regular fields and other to display fields from XmlFields field.
In Controller, I have following:
public ActionResult Create(Contact contact, FormCollection collection)
...
Regular field I catch with contact object and those that need to be stored as xml in XmlFields I try to catch with collection object. Problem is that collection object catches all fields, so I wonder if it is possible to isolate xml fields when posting to a specific object so that I can easily manipulate with them.
I need this in separated objects because these xml fields are going to be generated dynamically and will be different for every user.
Thanks in advance,
Ile
You can separate fields like:
public ActionResult Create(int ContactID, string FirstName)
And pass the raw data to the XML... There isn't any automatic way for MVC to know where to push what data to, unless you consider creating a custom model binder: http://davidhayden.com/blog/dave/archive/2008/09/08/CustomModelBinderMoreUIValidationASPNETMVC.aspx which is another valid option.
HTH.

Resources