Using pluralised table names with C# generics in MVC - c#

I'm trying to create a generic function that will be used to access multiple tables in my database. Is there a way to used pluralised (pluralized for the non-British!) table names with my generic function.
I may be thinking about this the wrong way (fairly new to generics/templates), but here's my code (Db is just a global var for access to my database):
public void UpdateMyTables<TEntity>() {
// string plural = EntityObject<TEntity>.GetTableName(); // OR SOMETHING SIMILAR??
IEnumerable<EntityType> entitiesToUpdate = Db.<TEntity>; // Obviously doesn't work because TEntity is not a table name, it's an object type
foreach(<TEntity> e in entitiesToUpdate) {
e.MyColumn = "A string that I'm updating all these fields with";
}
}
So my question is: do I need to do some hackery to get the pluralised table name, or is there a function designed to return this (like GetTableName), or should I come at this from a different angle?
I also found a link that would help with the manual conversion here: Pluralising in mvc
Hugs and kisses and thanks in advance...

You can use the .Set() method to get the IEnumerable:
IEnumerable<TEntity> entitiesToUpdate = Db.Set<TEntity>();
To get the Table Name you could possibly use the code from this blog post or this SO answer.
The foreach should be written:
foreach(TEntity e in entitiesToUpdate) { // you can use "var" here if you prefer
e.MyColumn = "A string that I'm updating all these fields with";
}
Now, the problem is that TEntity does not have a .MyColumn property. If you are using this method with entities that inherit from a base class (called for example BaseEntity), which has that property, you can change the method declaration like this:
public void UpdateMyTables<TEntity>() where TEntity : BaseEntity {
This limits you to pass to call this method only with Entities that inherits from BaseEntity, but will give you access to the public properties and methods defined in BaseEntity.
To make the code above work, Base Entity should be declared like this:
public class BaseEntity { //of course it can be abstract or an interface...
public string MyColumn { get; set; }
}
I hope I understood what you wanted to do. If you need further information let us know. :)

Related

Best approach to instantiate object based on string

I'd like to discuss about the best approach (in C#) to instantiate an object based on an input string. Let me explain.
Let'say I have a base class:
public abstract class BaseCar
{
public asbtract int GetEngineID();
//Other stuff...
}
Then I have several implementations of this class, let's say:
public class SportCar : BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
public class OtherCar: BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
And so on...
What I'd like to do is to make a static CarFactory class which has a CreateCar method which accepts a string as a parameter and returns a BaseCar instance, depending on what string you give. The string would be a name of a child class.
For example, if I call CarFactory.CreateCar('SportCar') it should return a SportCar instance.
I know I could use a simple switch statement to check which car has been requested and create a new instance based on that but I don't like this approach for two reasons:
I plan to have a lot of child classes, hard-coding every case wouldn't be too easy to mantain
I plan to implement an inizialization procedure to also give some initial values to the objects I create (using Reflection), so mixing hard-coding and reflection doesn't seem to be a good idea for me.
What I was thinking about is to use the Assembly.CreateInstance from System.Reflection to create an instance of the specified class but since this is the first time I approach this problem, I don't know if there are better ways to do that. Is this a valid approach ?
Considering the input string will come from an XML file, is there a simplier method ? Maybe my issue is already handled in some .NET Assembly which I'm missing.
Here is what I came up with. A generic factory class that automatically registers all types that are a subclass of the given type, and allows you to instantiate them via their name. This is somewhat related to the approach shown in the Java SO question linked by #Achilles in the comments, only that there is no initialisation function associated with the type.
There is no need to maintain an enum/switch combination of all types. It should also be somewhat easily extendable to handle your proposed reflection based initialisation.
static class StringFactory<T> where T : class
{
static private Dictionary<string, Type> s_dKnownTypes = new Dictionary<string, Type>();
static StringFactory()
{
RegisterAll();
}
static private void RegisterAll()
{
var baseType = typeof(T);
foreach (var domainAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in domainAssembly.GetTypes()
.Where(t => t.IsSubclassOf(baseType)))
{
s_dKnownTypes.Add(type.Name, type);
}
}
}
static public T Create(string _sTypeName)
{
Type knownType;
if (s_dKnownTypes.TryGetValue(_sTypeName, out knownType))
{
return (T)Activator.CreateInstance(knownType);
}
throw new KeyNotFoundException();
}
}
Assuming the classes of your question exist, you would instantiate a specific car like this:
var car = StringFactory<BaseCar>.Create("SportsCar");
DoSomethingWith(car.EngineID());
Since your question was for a discussion about the best approaches, please consider this only one of them. I have not used this in a production environment, and it is entirely possible that it is the wrong approach to your specific situation. It works well enough to show the general principle, however, and should provide a starting point for further discussion.

How to pass object attributes as function parameters?

I am designing a 3 layer framework
I would like to know if It's possible to pass attribiutes of an object to a function without declaring them explicitly ?
For example If I want to pass Id,Name to personnelBL.ValidateInsert(...)
I don't want the ValidateInsert function interface look like this : ValidateInsert(Id,Name)
The reason for that is that I want to write a base abstract class to contain a ValidateInsert(...)
abstract function so I will Inherit from that class in my BL Layer classes and If the ValidateInsert input parameters could be declared in a way that I could pass an object attribiutes in a general form It would really be nice .
Note: Someone might say that I can pass an object to the function using generics but I really don't want to pass an object ! I want to pass any object's attribiutes so I can Inherit that abstract base class in any entityBL classes .
I really could not explain what I want better ! Sorry for that and thanks for understanding me .
not sure that I fully understand what you want , but I think the below can help
You can use reflection.You can avoid the performance issues, is you create method per class on the fly and compile it (can use compile expression tree). and add your own attribute that you put only on relevant attributes.
Create an Interface, It can return dictionary of column name and their values. your abstract class will implement this interface.
hope this answer your question
I am not sure if i understand your question correctly, but are you looking for something similar to this-
public class Base<T, TFiled>
{
public void ValidateInsert(TFiled filed)
{
}
}
public class Derived : Base<Derived, long>
{
public long Id { get; set; }
}
public class AnotherDerived : Base<Derived, string>
{
public string IdSring { get; set; }
}
public class MyObject
{
private Derived d = new Derived();
private AnotherDerived anotherIsntance = new AnotherDerived();
public MyObject()
{
d.ValidateInsert(10);
anotherIsntance.ValidateInsert("some string");
}
}
Well, not really.
But you can get very close to!
You can use the Expression API. It's awesome. The code I'll post here is just pseudocode but you'll get the idea. I'll not worry about syntax but I'll try the hardest I can.
public static bool ValidateInsert(params Expression<Func<object,object>>[] properties)
{
//Here you'll do some code to get every property. You can do a foreach loop.
//I think you will need to use reflection to get the property values
} //Change Func<Object,Object> accordingly. This represents a function that takes an object and returns another object.
This is how you can achieve the syntax, but I'm not sure about functionality.
You'll need an "instance" object where you'll get the properties values from.
So, you could call it like this:
ValidadeInsert(x => x.Id, x => x.Name, x => x.Whatever)
Here you can see how to get the Getter method of a property. I think you can get the PropertyInfo from the lambda expression, but I'm not sure. You'll have to do some research and adapt it to your code, if you decide to follow this way.
Sorry about my english, but I think you understood what I meant.

Best way to save type of class in database?

What is a good way to denote "type" in database?
I have a base class Action which is inherited by numerous child classes. Action has members like Id, Name etc all which corresponds to equivalent columns in a table in the database called action. So action table looks like this:
id | name | type
The type column denotes what action it is. In my code they correspond to the child classes deriving from parent Action. Now how do I save the type of class to the type field in database?
The type column in db could be of any data type.
Options:
Save action.GetType().ToString() as string in db. And get the action type from db back by converting the string representation of the type to its original type using reflection. But this will be problematic if class names change in future.
Create an enum to denote each child class and decorate it by a TypeAttribute, something like:
public abstract class Action
{
public enum Kind
{
[Type(typeof(ControlAction))]
ControlAction = 1,
[Type(typeof(UpdateAction))]
UpdateAction = 2,
etc
}
public abstract Kind ActionType { get; }
}
public class ControlAction : Action { public override Kind ActionType { get { return Kind.ControlAction; } } }
public class UpdateAction : Action { public override Kind ActionType { get { return Kind.UpdateAction; } } }
//etc
This looks good, except that for each class from here onwards I have to create an enum. And it feels like a little too much work to be done.
Build a separate static hash table of <int, Type> that ties a class to a int value. May be a little bit unreadable.
Is there a better solution to this?
I would go from the 3rd solution with a hash-table, as it does seem to be the cleaner design-wise. And I would delegate its management to the database!
After all, isn't this what relational databases excel at the most, creating relations between two entities (in your case, action and type)? Other advantage is you end up with a normalized schema (sure, so far, there is only one column to the type table, namely its name, but normalizing allows you to easily add additional attributes to the types should you need them in the future, which is why it is cleaner as a design).
The schema would be something like this:
Action table
action_id(PK) | name | type_id (int, FK to Type table)
Type table
type_id(PK) | type_name
Now you are safe if the name of a class changes in the future (concern from your first proposition with string type). Indeed, all you would do is change the type_name value in the corresponding Type table row and all your Action rows would still be linked to this row by the type_id, which never changes once created (no problem here, as it does not hold any "business meaning").
And you have your hash-table from 3 (the Type table) in a readable format as it is the RDMBS's responsibility to manage the keys of the hash-table (the type_id PK).
Note that you won't have to tie your class to an int value corresponding to the type_id column, but rather fetch from the Type table the type_id by looking it up against the Class type (type_name).
I ended up using option 2, but with less clutter of attributes. Something like this:
public abstract class Action
{
public enum Kind
{
ControlAction = 1,
UpdateAction = 2,
etc
}
public abstract Kind ActionType { get; }
}
public class ControlAction : Action { public override Kind ActionType { get { return Kind.ControlAction; } } }
public class UpdateAction : Action { public override Kind ActionType { get { return Kind.UpdateAction; } } }
The biggest advantage for this is that (even if it meant more typing), it enforces a numeric value to be associated with a class type.
Now class to int is just:
var value = (int)instance.ActionType;
Very fast.
But to convert int to class instance (or class type), I will have to create an instance of each sub action types, and compare its ActionType property to match the input int value. This is going to be slow. But I can cache somethings and make it faster. Something like:
static readonly Dictionary<Action.Kind, Type> actionTypes =
GetDefaultInstanceOfAllActions().ToDictionary(x => x.ActionType, x => x.GetType());
public static Action ToAction(this Action.Kind value)
{
return (Action)Activator.CreateInstance(actionTypes[value]);
}
The GetDefaultInstanceOfAllActions does some reflection (once) to get all types of actions (I use something like this answer for that). I can even make the make the instantiation faster by going the expression route.
The benefits:
Less hassle when creating a new class (no attributes).
Enforces an int to be tied to a class type.
Moderately fast with adequate caching.
I would go with your first option and use reflection. It seems more likely that you will want to add new action types rather than change existing class names and therefore the ease of serializing the type using reflection is more useful.
You could then just have a utility class for serializing actions and restoring them from their type string.

Extend (not change) search class for new behaviour?

I'm making a change to an API that serves data (this is an update to my original question). Some of the searches require data about an author and take a IAuthor object. The API has an IAuthor interface and a single concrete class that implements IAuthor called Author.
I need to change the behaviour of the Search.GetBooksByAuthor method to give different semantic when the author is flagged as a novelist. I've heard about the open/closed principle and it would seem that changing the IAuthor and/or Author and/or Search classes would violate this (the Book class is definitely remaining unchanged, though). How then to make this simple change?
For example, I was originally thinking something like this but my thinking is probably wonky because it involves changing the Search class:
//Before
class Search
{
public Books[] GetBooks(IAuthor author){
// Call data access GetBooks...
}
}
//After
class Search
{
public Books[] GetBooks(IAuthor author){
// To maintain pre-existing behaviour
// call data access GetBooks method with SQL param #AsNovelist = false...
// (or don't pass anything because the SQL param defaults to false)
}
public Books[] GetBooksAsNovelist(IAuthor author){
// To get new behaviour
// call data access GetBooks method with SQL param #AsNovelist = true
// so that their non-fiction books are omitted from results
}
}
It may seem obvious that something has to change to cater for knowing whether or not your author is a Novelist, you could do this one of two ways. You don't have to change anything in theory, you do however need a new class.
public class Novelist : Author, IAuthor { }
Then you can pass a novelist into your method and then deterimne your type of author.
class Search
{
public Books[] GetBooks(IAuthor author){
if(author is Novelist)
//Do some stuff or set a flag/bool value
}
}
OR as previously mentioned, implement a boolean member to your Author interface and check that. The above would prevent you changing your class structures however.
This means that your novelist is in fact still an author, it just has it's own type. Your method signatures remain the same, your class structures remain the same you just have a type for a "different type of author", which should in theory be fine. Call as below to test.
GetBooks(new Novelist());
How about using a predicate for filtering?
class Search
{
public Books[] GetBooks(IAuthor author, Func<IAuthor, bool> filter){
// ...
}
}
search.GetBooks(author, a => a.IsNovelist)
In order to extend classes C# .NET introduced extension methods in .NET 3.5 whose main purpose is precisely to extend a class without modifying the existing code:
public static class SearchExtensions
{
public static Books[] GetBooksAsNovelist(this Search search, IAuthor author)
{
// Perform novelist search
}
}
Then you can invoke your Search class normally with:
Search.GetBooksAsNovelist(author);
You can use the Extension feature of C# language.
Please see http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx
Extensions enable to add functionality to class by keeping the class intact.
In your case you can write as:
public static class SearchExtensions
{
public static Books[] GetBooks(this Search search, IAuthor author)
{
//new logic
}
}
You can access this new method by Search object and Search class also remains intact.
Please let me know if you find this helpful.
You could make your class partial to be able to add functionalyti without extensions, or inheritance, or inversion of control:
// file: Search.cs
partial class Search
{
public Books[] GetBooks(IAuthor author) { ... }
}
// file: Search.Advanced.cs
partial class Search
{
public Books[] GetBooksAsNovelist(IAuthor author) { ... }
}
Results:
http://i.snag.gy/VowNv.jpg
Keep the search class methods as virtual thus anyone can override them creating a new behavior?

c# DAL - Interface for business objects

I have a Report Interface which has a Run method.
There are different types of reports which implement this interface and each run their own kind of report, getting data from different tables.
Each report, using its own data context, gets data which then populates Business Objects with and at the moment they are returned as an array (I would like to be able to at least return something like a list but because you have to define the list type it makes it a bit more difficult).
Reflection is then used to find out the properties of the returned data.
I hope I have explained this well enough!
Is there a better way of doing this?
By request:
public interface IReport
{
int CustomerID { get; set; }
Array Run();
}
public class BasicReport : IReport
{
public int CustomerID { get; set; }
public virtual Array Run()
{
Array result = null;
using (BasicReportsDataContext brdc = new BasicReportsDataContext())
{
var queryResult = from j in brdc.Jobs
where j.CustomerID == CustomerID
select new JobRecord
{
JobNumber = j.JobNumber,
CustomerName = c.CustomerName
};
result = queryResult.ToArray();
}
}
}
The other class then does a foreach over the data, and uses reflection to find out the field names and values and puts that in an xml file.
As it stands everything works - I just can't help thinking there is a better way of doing it - that perhaps my limited understanding of C# doesn't allow me to see yet.
Personnally I would first ask myself if I Really need an interface. It would be the case if the classes implementing it are Really different by nature (not only by report kind).
If not, i.e all the implementing classes are basically "Reporters", then yes, there is a more convenient way to do this which is :
Writing a parent abstract Report
Having a virtual Run method and the CustomerID accessor
inheriting your "Reporter" classes from it

Categories

Resources