I want to display a bunch of different data objects that I have using WPF. These data objects vary in data. They have common properties, but they also have some differing properties. There will be a "master" class that references these entities. Each master class can have one of each of these data types.
I'm finding it difficult to design them even on a database level. Should I have one table per data object, thereby making it easy to get the data using NHibernate (just reference one of these entities). This makes it quite difficult to consume using WCF though. If I'm wanting to display this data in WPF, I'll probably need a collection of some variety, and that's what I don't have.
I could put all data types into the same table and have a multi-column unique constraint on the owner id and data type id. But then I may have null properties in my entities, and it would also be hard to display in the UI. It would also complicate editing the entities, as I'd have to mindful of which properties the user can and can't edit.
I guess visually, the entities would look like this in the first way:
public class Master
{
int Id
DataType1 Data1
DataType2 Data2
}
public class DataType1
{
int Id
string SomeString
string AnotherString
}
public class DataType2
{
int Id
string SomeString
string DifferentString
}
And this in the second way:
public class Master
{
int Id
List<DataType> Types
}
public class DataType
{
int Id
string SomeString
string AnotherString
string DifferentString
}
So which would be the best way? Or is there a different way that's better than both (there probably is)?
It is really depend on your business case as it is not such an architectural issue. If you have known number of DataType-s do static (one to one) reference (first example).
If you have unknown or dynamic number of the DataType-s you have no other option than to make these DataType-s as a list in your "Master" object.
Related
I am doing this project in c# and when designing a database, i am using a rule that each class is basically sql table (at least the class that has to be persisted).
Since some classes are purely used to define business settings and the classes are rather flat, I am curios does it make any sense to do something like this..
Transform business layer class
class Contact
{
public string Name {get;set;}
public string PhoneNumber {get;set;}
public bool AcceptsTextMessages {get;set;}
public bool AllowedHoursForTextMessagesStart {get;set;}
public bool AllowedHoursForTextMessagesEnd {get;set;}
public List<DayOfWeek> SendMessagesOnlyOnWorkdays {get;set;}
}
to a data layer class that look something like (and persist it in sql)
public Settings
{
public ID {get;set}
public Name {get;set}
public Value {get;set;}
}
with real life data
ID Name Value
1 Name John Doe
2 PhoneNumber 01234657
3 ExceptsTextMessages true
4 AllowedHoursForTextMessagesStart 0
5 AllowedHoursForTextMessagesEnd 24
6 SendMessagesOnlyOnDays 1,2,3,4,5
The primary reason for this is to have one settings table instead of having as many tables as classes, possibly easier class modification, easier manipulation of properties between classes (in case there is a business logic need to move one property from one class to another)
Decomposing your objects into IDs and attribute-value pairs is one of those techniques that's sometimes extremely useful. EAV data is much more complicated to manage than a flat table with individual columns, so it's not something to implement lightly.
Given what you've posted, I probably wouldn't. All the fields you have seem reliably relevant to being-a-contact and unlikely to require changing around dynamically in production (since one starts or stops accepting text messages, rather than ascending to a plane of existence where text messages are epistemologically irrelevant).
Even if it made sense to represent certain fields as pairs, I'd only do it for those fields: keep a users table with a primary key and the essential data, then put the rest off in an EAV table with a foreign key relationship to users.
I'm porting old VB6 code (yes yes, VB6...) to C#. I'm refactoring code to be more object-oriented, and among other things, I'm implementing repository classes to access the database.
Now, these repository classes return objects, not datasets. But I find that sometimes I only return a subset of the information an object might hold. Example: I can get a complete list of documents, with name, filepath, folder, creator, etc - or I can get document search results which only contain name and folder.
What is the best practice for these subset cases? Should I create custom objects for these database calls, that only contain the subset of data? Should I return the complete objects with only some of their fields populated? Or should I just return datasets?
Ideally, everything should be centralized as much as possible. This could be done by creating a query object for each subset. I think you can go either way with returning objects with some fields populated or null, dependent if your database allows nulls for those specific fields.
So centralize your rules and logic with your repository classes so that each object is returned consistently based on those rules and logic.
Create an underling schema for your objects so they do not get too complex. I think what is need is an entity per object to be consider for repository. Again, creating custom objects or DTO's could create unneeded code and complexity. For the sake of integrity, keep your objects with some fields populated and others that are not needed within that subset null, that way if this information is queried later, information can be reported back that value does not exist for a specific entity.
Here is a brief example, try using POCO classes with the entity framework.
public interface IRepository<TEntity, in TKey> where TEntity : class
{
TEntity Get(TKey id);
}
public class SomeRepo1 : IRepository
{
private readonly FileDbContext someDbContext;
public FileRepository(FileDbContext dbContext)
{
someDbContext = dbContext;
}
public File Get(string id)
{
return someDbContext.Files.ToList();
}
}
Example of POCO Class that can be used for files:
public class File
{
public int Id { get; set; }
public string FileName { get; set; }
}
public class Folder
{
public List<File> Files { get; set; }
}
More details here: https://msdn.microsoft.com/en-us/library/ff649690.aspx
Hope this helps!
But I find that sometimes I only return a subset of the information an object might hold.
You have just confused the object model with the persistence model.
You see, the object model doesn't care how the storage is implemented. Specifically, if there is a database behind the object model and you have tables that contain some data, you are free to map the database to your object model in any way you want. With a clever object-relational mapper you can for example split a table into two classes or have multiple classes persisted in the same table.
So, something that looks like "a subset" from the perspective of your storage, could possibly not be "a subset" from the object-model perspective.
An example specific Entity Framework 6 solution involves so called Table Splitting which allows you to split a model class into two classes, a class with core properties that are always loaded and another class with auxiliary properties that are lazily loaded only when you refer to the virtual property of the core class.
An example tutorial: http://www.c-sharpcorner.com/UploadFile/ff2f08/table-splitting-in-entity-framework-6-code-first-approach/
(just to mention, the opposite, where two physical tables are mapped to oe model class is called Entity splitting)
I want to improve one of my current applications that uses ADO Data Sets. The application is standalone, no DBs. Almost everyone says that ADO Data set is an old stuff and a much better approach is using your own structures. For example I have the data model below (the same kind of model we usually use with Entity Framework):
public class Customer
{
public int ID {get;set;}
public string Value {get;set}
public IEnumerable<Order> Orders {get;set;}
}
public class Order
{
public int ID {get;set;}
public string Value {get;set}
public Customer Customer {get;set;}
}
I don't understand the next:
How to store class model in memory. Just in a simple List<>. It is not efficient with searching. In SQL we can make indexes for two often used columns and optimize our search. Can we do something similar (fast indexed search by multiple columns) in memory? If can, please explain me how. In DataTables we can use Primary Key as index.
Is a good data structure exist. A structure that allows binding to DataGrids, Fast indexed search by multiple columns, LINQ. Or we need to store everything in List<> or Hashset<> and prepare some additional structures for fast searching.
Scenario: I am writing a program that handles report generation.
I have the report stored in a database, mapped to an EF model. There are some non-database fields (i.e. some fields are auto-calculated based on other fields that ARE in the db). Would it make sense to have one class that solely maps to the DB, and another class that takes that information and additionally has the other calculating fields?
i.e. a sample class to interact with the codefirst database would be
public class Report{
public int CategoryOneSeverity {get; set;}
public int CategoryTwoSeverity {get;set;}
public string Title {get;set;}
}
Would it make sense to make another class, like:
public class ReportModel{
public int CategoryOneSeverity;
public int CategoryTwoSeverity;
public string Title;
public int RiskRating{
get{ return CategoryOneSeverity + CategoryTwoSeverity; }
}
}
Or should the RiskRating property be in the EF model.
Yes, I absolutely believe you should have different classes to model your domain than your DB. Unless your application is extremely trivial, if you try to map your domain objects directly, you invariably have to change them to match what you need your data structure to be, and possibly expose things you don't want to expose. Think of it as a violation of the Single Responsibility principle; your class has two reasons to change if you make it your domain object and map it directly. One is in response to changing business requirements, the other is in response to changing data storage schema.
"Would it make sense to have one class that solely maps to the DB, and
another class that takes that information and additionally has the
other calculating fields?"
Most likely yes. Usually I would create a new class suffixed with "ViewModel" such as HumanResourcesReportViewModel if my entity class was HumanResourcesReport.
There's lots of variations on how to use ViewModels, and we could get into a pedantic debate about terminology, but conceptually, take your entity and create a new class with that data plus whatever additional information you need to process the report. In this case the report generation is in a way the View of the MVC model, so I don't think it's offensive to call the class holding the data a ViewModel.
Are you using Code First or DB First?
You can have auto calculated fields in your model, which are not mapped to fields in the database.
It also depends on your architecture. If you're using DB first, refreshing your EF model would update your EF classes, losing your mapped fields. In the DB-First scenario, an alternative would be to use the EF model class as your base class and inherit from it for your report class.
public class ReportModel
{
public int CategoryOneSeverity;
public int CategoryTwoSeverity;
public string Title;
}
public class ReportClass : ReportModel
{
public int RiskRating
{
get { return CategoryOneSeverity + CategoryTwoSeverity; }
}
}
So, I'd love some feedback on the best way to design the classes and store the data for the following situation:
I have an interface called Tasks that looks like this:
interface ITask
{
int ID{ get; set;}
string Title {get; set;}
string Description{get; set;}
}
I would like the ability to create different types of Tasks depending on who is using the application...for example:
public class SoftwareTask: ITask
{
//ITask Implementation
string BuildVersion {get; set;}
bool IsBug {get; set;}
}
public class SalesTask: ITask
{
//ITask Implementation
int AccountID {get; set;}
int SalesPersonID {get; set;}
}
So the way I see it I can create a Tasks table in the database with columns that match the ITask interface and a column that shoves all of the properties of more specific tasks in a single column (or maybe even serialize the task object into a single column)
OR
Create a table for each task type to store the properties that are unique to that type.
I really don't like either solution right now. I need to be able to create different types of Tasks ( or any other class) that all share a common core set of properties and methods through a base interface, but have the ability to store their unique properties in a fashion that is easy to search and filter against without having to create a bunch of database tables for each type.
I've starting looking into Plug-In architecture and the strategy pattern, but I don't see where either would address my problem with storing and accessing the data.
Any help or push in the right direction is greatly appreciated!!!
Your second approach (one table per type) is the canonical way to solve this problem - while it requires a bit more effort to implement it fits better with the relational model of most databases and preserves a consistent and cohesive representation of the data. The approach of using one table per concrete type works well, and is compatible with most ORM libraries (like EntityFramework and NHibernate).
There are, however, a couple of alternative approaches sometimes used when the number of subtypes is very large, or subtypes are created on the fly.
Alternative #1: The Key-Value extension table. This is a table with one row per additional field of data you wish to store, a foreign key back to the core table (Task), and a column that specifies what kind of field this is. It's structure is typically something like:
TaskExt Table
=================
TaskID : Number (foreign key back to Task)
FieldType : Number or String (this would be AccountID, SalesPersonID, etc)
FieldValue : String (this would be the value of the associated field)
Alternative #2: The Type-Mapped Extension Table. In this alternative, you create a table with a bunch of nullable columns of different data types (numbers, strings, date/time, etc) with names like DATA01, DATA02, DATA03 ... and so on. For each kind of Task, you select a subset of the columns and map them to particular fields. So, DATA01 may end up being the BuildVersion for a SoftwareTask and an AccountName for a SalesTask. In this approach, you must manage some metadata somewhere that control which column you map specific fields to. A type-mapped table will often look something like:
TaskExt Table
=================
TaskID : Number (foreign key back to task)
Data01 : String
Data02 : String
Data03 : String
Data04 : String
Data05 : Number
Data06 : Number
Data07 : Number
Data08 : Number
Data09 : Date
Data10 : Date
Data11 : Date
Data12 : Date
// etc...
The main benefit of option #1 is that you can dynamically add as many different fields as you need, and you can even support a level of backward compatibility. A significant downside, however, is that even simple queries can become challenging because fields of the objects are pivoted into rows in the table. Unpivoting turns out to be an operation that is both complicated and often poorly performing.
The benefits of option #2 is that it's easy to implement, and preserves a 1-to-1 correspondence betweens rows, making queries easy. Unfortunately, there are some downsides to this as well. The first is that the column names are completely uninformative, and you have to refer to some metadata dictionary to understand which columns maps to which field for which type of task. The second downside is that most databases limit the number of columns on a table to a relatively small number (usually 50 - 300 columns). As a result, you can only have so many numeric, string, datetime, etc columns available to use. So if you type ends up having more DateTime fields than the table supports you have to either use string fields to store dates, or create multiple extension tables.
Be forewarned, most ORM libraries do not provide built-in support for either of these modeling patterns.
You should probably take a lead from how ORMs deal with this, like TPH/TPC/TPT
Given that ITask is an interface you should probably go for TPC (Table per Concrete Type). When you make it a baseclass, TPT and TPH are also options.