Generic Types and LINQ - c#

I write two public classes (test1, test2) with two fields, e. g. 'Name' and 'Surname'.
Then, I would like to fill data from a database to this objects.
My first try was:
public List<T> FillFromDB<T>()
{
IQueryable<T> query =
from tbl in _table
select new T {Name=tbl.name, Surname=tbl.surname}
}
But T don't know the fields. What could I do? Thanks for your help.

You can create a common interface (or class) from which Test1 and Test2 would inherit from and then specify the necessary constraints on the type parameter of FillFromDb.
public interface IHasName
{
public string Name { get; set; }
public string Surname { get; set; }
}
public class Test1 : IHasName
{
public string Name { get; set; }
public string Surname { get; set; }
}
public class Test2 : IHasName
{
public string Name { get; set; }
public string Surname { get; set; }
}
public List<T> FillFromDB<T>()
where T : new(), IHasName
{
IQueryable<T> query =
from tbl in _table
select new T {Name=tbl.name, Surname=tbl.surname}
}

Related

How to select certain fields from class with IQueryable?

I have an IQueryable<MainObjectTest> in which there are several fields, but I only need to pull out certain ones (Title and NestedObject).
How can I do this with dynamic select expression?
public class TestIQueryable
{
public IQueryable GetObjectData(IQueryable<MainObjectTest> data)
{
IQueryable requredDataFields = data.Select("new(Title, NestedObject)");
return requredDataFields;
}
public class MainObjectTest
{
public string Title { get; set; }
public DateTime Date { get; set; }
public NestedClassTest NestedObject { get; set; }
}
public class NestedClassTest
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
}
}
What about making an interface:
interface Interface1
{
public string Title { get; set; }
public NestedClassTest NestedObject { get; set; }
}
Implement the interface in you class and let GetObjectData return the interface
public IQueryable GetObjectData(IQueryable<Interface1> data)
{
IQueryable requredDataFields = data.Select();
return requredDataFields;
}
I solved my problem using model, here steps:
Map all data from database into model if you have nested object => use ToList().
Use DynamicLinq library to select certain fields from model as IQueryable.
Hope it helps someone!
Use an anonymous object like this.
IQueryable requredDataFields = data.Select(x => new { x.Title, x.NestedObject });

Generic Type Constraint where class implements an abstract class

I have an Generic Abstract Class with some properties like Id, Name, Status, this class inherits several catalogs.
My question is whether it is possible to create a method with a restriction for the catalogs that implement the Abstract Class.
I give some examples so that they understand what I want to do:
public abstract class AbsCatalog<T>
{
public T Id { get; set; }
public string Name { get; set; }
public bool Status { get; set; }
}
These are the classes that implement the abstract class
public class Agent : AbsCatalog<string>
{
public string Office { get; set; }
public Estado Estado { get; set; }
}
public class Models : AbsCatalog<int>
{
public int Year { get; set; }
public string Description { get; set; }
}
The method I want to implement is the following:
List<Agent> Agents = service.GetAgents();
string AgentsDescription = GetDescription<Agent>(Agents);
List<Model> Models = service.GetModels();
string ModelsDescription = GetDescription<Model>(Models);
private string GetDescription<T>(List<T> list) where T : AbsCatalog<T>
{
string description = string.Empty;
if (list.Exists(x => x.Id.ToString() == "0"))
description = "";
else
description = string.Join(", ", list.Where(x => x.Status).Select(x => x.Name).ToArray());
return description;
}
I think the only way is to use two generic type parameters here, for example:
private string GetDescription<T, U>(List<T> list) where T : AbsCatalog<U>
{
//snip
}
And then call it like this:
string AgentsDescription = GetDescription<Agent, string>(Agents);

Derive properties as per the requirement...?

So, I have 3 fields/properties. Say, they are, paramA, paramB, paramC. And I’ve three classes as Class A, Class B, Class C.
Requirement is to use:
• paramA, paramB in Class A
• paramA, paramC in Class B
• paramB, paramC in Class D
Is there any way to declare all these 3 properties in a common place and derive in the A,B,C classes as per the requirement....?
UPDATE
Please find some more details of the requirement:
The real requirement is:
There is a table ‘Que Table’ in database which is having following fields
• bool IsQb
• bool IsOverride
• string Identifier
• string userlogin
• FolderName
Following model classes are using for create/update/delete data in ‘Que Table’.
• CreateQue class
• UpdateQue class
• DeleteQue class
CreateQue class only requires the properties:IsQb, IsOverride,UserLogin, FolderName
UpdateQue class only requires the properties: IsQb, IsOverride, Identifier, UserLogin, FolderName
And DeleteQue class only requires: Identifier property.
The code for the model classes are:
public class CreateQue
{
public bool IsQb { get; set; }
public bool IsOverride { get; set; }
public string userlogin { get; set; }
public string FolderName { get; set; }
}
public class UpdateQue
{
public bool IsQb { get; set; }
public bool IsOverride { get; set; }
public string Identifier { get; set; }
public string userlogin { get; set; }
public string FolderName { get; set; }
}
public class DeleteQue
{
public string userlogin { get; set; }
public string Identifier { get; set; }
}
So, is there any pattern/architecture out there to declare all those properties in a single place and derive as per the requirement in those model classes....? Thanks in advance
It's a bit unclear what you need to do as we can't see your requirements. You could use interfaces:
public interface IHasPropertyA
{
string PropertyA { get; set; }
}
public interface IHasPropertyB
{
string PropertyB { get; set; }
}
public class ClassA : IHasPropertyA, IHasPropertyB
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
}

Better Search DTO Design

How do I make a generic SearchDTO which can be used as a template for any Search?
It should have any filter and other general information like TotalRecords, Sort Order, Pages, Start Row, etc
public abstract class SearchDTO
{
public object Id { get; set; }
public IList<T> SearchResults { get; set; }
public int PageSize { get; set; }
public int StartRowNo
{
get
{
return (CurrentPage - 1) * PageSize;
}
}
public int CurrentPage { get; set; }
}
And any Search Object looks like.
public class EmployeeSearchDTO:SearchDTO
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
But I get the following error in IList<T> property:
The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?).
How could I specify like returing a List of any objects and I can create other property like
public long TotalRecords
{
get
{
return SearchResults.Count;
}
set;
}
Is there any best approach other than this to solve this?
You need to specify T as type parameter on your class:
public abstract class SearchDTO<T>
Then when you will inherit from it - you should either provide concrete type instead of type parameter:
public class EmployeeSearchDTO : SearchDTO<MyConcreteType>
or successor class should be generic as well:
public class EmployeeSearchDTO<T> : SearchDTO<T>
You need the declaration on the class as well, to know what type T is:
Code for abstract class
public abstract class SearchDTO<T>
{
public object Id { get; set; }
public abstract IList<T> SearchResults { get; set; }
public int PageSize { get; set; }
public int StartRowNo
{
get
{
return (CurrentPage - 1) * PageSize;
}
}
public int CurrentPage { get; set; }
}
IList<T> SearchResults must be declare as abstract and override in inherited class.
Code of EmployeeSearchDTOP
public class EmployeeSearchDTO:SearchDTO<Employee>
{
public override IList<Employee> SearchResults { get; set; }
}
Create Employee class and move FirstName & LastName properties in Employee class.
Employee Class
public class Employee
{
public string FirstName {get; set; }
public string LastName {get;set;}
}
Until and unless there is a specific reason for you to use a abstract class what you want can be achieved by simply using a template class:
public class SearchDTO<T>
{
public object Id { get; set; }
public IList<T> SearchResults { get; set; }
public int PageSize { get; set; }
public int StartRowNo
{
get
{
return (CurrentPage - 1) * PageSize;
}
}
public int CurrentPage { get; set; }
}
For creating object all you need to do is this:
SearchDTO<EmployeeSearchDTO> obj=new SearchDTO<EmployeeSearchDTO>();
And instead of having SearchResults property create a function that would return a list of EmployeeSearchDTO objects, like this:
public IList<T> SearchResults()
{
IList<T> listObj=new List<T>();
//your code here
return listObj;
}

Issue with generics in c#

I have a problem while adding a new class in my existing structure. I am going to explain my problem as much clear as i can
public interface Imust
{
string Name { get; set; }
string File { get; set; }
string RowKey { get; set; }
string Time { get; set; }
string PartitionKey { get; set; }
}
public class TA : TableServiceEntity, Imust
{
public string Time { get; set; }
public string Name { get; set; }
public string File { get; set; }
}
public class TB : TableServiceEntity, Imust
{
public string Time { get; set; }
public string Name { get; set; }
public string File { get; set; }
}
public class TC : TableServiceEntity, Imust
{
public string Time { get; set; }
public string Name { get; set; }
public string File { get; set; }
}
public class _Table <T> : _Account where T : Imust
{
}
Here the above 3 classes are implemented as Tables and its properties as its columns in my project. Imust interface is implemented in each class because in generic class i put an interface constraint. TableServiceEntity class contains the implementation for RowKey and PartitionKey.And this class is also inherited in all 3 entities.
Problem : Now i have to add a new table in my application. So for this i have to add a new class here which is
public class TD : TableServiceEntity
{
}
I do not want this class to implement the Imust interface because it does not contain these columns. But i have to pass it as a parameter in generic class _Table.Because this new class has different columns but it perform same function which other 3 entities does. Now how will i add this new class while maintaining my existing structur ?
Please suggest me any better solution for this problem ?
EDIT
Yes i can put a constraint TableServiceEntity as a base class. But in generic class _Table there are few function which operate on File property like
public T AccessEntity(string Id = "0", string File = "0")
{
return (from e in ServiceContext.CreateQuery<T>(TableName)
where e.RowKey == Id || e.File == File
select e).FirstOrDefault();
}
If i removed this interface constraint then it shows an error that T does not have a defination for File.
I'd do this... the interface has no sense in your declaration as the more generic type for table is TableServiceEntity
public class _Table <T> : _Account where T : TableServiceEntity
{
}
Split the interface in two:
public interface Ibase
string RowKey { get; set; }
string PartitionKey { get; set; }
}
public interface Imust : Ibase
{
string Name { get; set; }
string File { get; set; }
string Time { get; set; }
}
public class TA : TableServiceEntity, Imust
{
public string Time { get; set; }
public string Name { get; set; }
public string File { get; set; }
}
public class TB : TableServiceEntity, Imust
{
public string Time { get; set; }
public string Name { get; set; }
public string File { get; set; }
}
public class TC : TableServiceEntity, Imust
{
public string Time { get; set; }
public string Name { get; set; }
public string File { get; set; }
}
public class _BaseTable <T> : _Account where T : Ibase
{
}
public class _Table <T> : _BaseTable<T> where T : Imust
{
}
And implement common functionality in _BaseTable and this specific to Time, Name and File in _Table.
It's even more intuitive after and edit you have made to your question. Thos methods in _BaseTable that rely on File, Name or Time can be marked abstract and overriden in _Table.
Updated to reflect posters additional info:
You need to specify a new Interface:
public interface IMust2 {
public string File {get;set;}
public string Rowkey {get;set;
}
Modify IMust to inherit from IMust2
public interface IMust : IMust2
{
public string Name {get;set;}
public string Time {get;set;}
public string PartitoinKey {get;set;}
}
Why not just have _Table be of <TableServiceEntity> type? Obviously, you are breaking your interface, so you can't keep using it as the generic as not every class will be of that interface?
You have 3 classes (TA, TB and TC) that are exactly the same. Why don't you have a single class, though?
For behavior (that is, methods), use a interface. For structure (that is, properties), use inheritance (like at TableServiceEntity).
Make TD inherit from the base class but do not implement the interface.
Change the restriction at _Table to be where T : TableServiceEntity
Regards

Categories