I created a property class representing the table schema of my SQLite database. Each attribute in the class become one attribute in the database.
class SQLiteTables
{
public class tblPerson
{
[PrimaryKey, AutoIncrement]
public int PersonID { get; set; }
public string PersonFirstName { get; set; }
public string PersonMiddleName { get; set; }
public string PersonLastName { get; set; }
}
public class tblSchedule
{
[PrimaryKey, AutoIncrement]
public int ScheduleID { get; set; }
public string ScheduleDescription { get; set; }
public DateTime ScheduleStart { get; set; }
public DateTime ScheduleEnd { get; set; }
}
//18 more table definitions below
}
Now, to retrieve some data from a table,
public void GetPersonList()
{
List<tblPerson> lstTemp = dbConn.Table<tblPerson>().ToList<tblPerson>();
// Some 20 lines of code here
}
I want to avoid writing type-specific methods, well it's kind of a tedious task. I want to create a reusable method which can retrieve data on any table using generics implementation. How can I achieve this?
EDIT I am working on a Windows Phone 8 platform.
This should work for what you're doing.
public List<T> GetItems<T>()
{
return dbConn.Table<T>().ToList<T>();
}
You could use DBLinq, which has support for SQLite - then you get your syntax for free on the data context.
public IList<T> GetList<T>()
{
return _context.GetTable<T>().ToList();
}
public IEnumerable<T> GetItems<T>() where T: new()
{
lock (locker) {
return dbCon.Table<T> ().ToArray ();
}
}
I think the key is the ":new()" at the end
Related
I have several classes that I need to store in a MongoDb collection, these classes have a common base class and common interface defining the common fields. Every class have a computed field with the same name but with different implementations. When I try to query on that field I get the message that the field is not supported
I'm running this on a .Net Core 2.2 console application with the latest MongoDb Driver
Interface:
public interface ITask
{
ObjectId Id { get; set; }
TaskStatus Status { get; set; }
DateTime Timestamp { get; set; }
string UserId { get; set; }
string ComputedField{ get; }
}
Base Class:
public abstract class BaseTask : ITask
{
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId Id { get; set; }
[BsonElement("Status")]
public TaskStatus Status { get; set; }
[BsonElement("Timestamp")]
public DateTime Timestamp { get; set; }
[BsonElement("UserId")]
public string UserId { get; set; }
public virtual string ComputedField
{
get { return CalculateMD5Hash(Id.ToString()); }
}
}
Actual class that give me the problem
public class MyTask : BaseTask
{
[BsonElement("Field1")]
public Guid Field1{ get; set; }
[BsonElement("ComputedField")]
public override string ComputedField
{
get { return CalculateMD5Hash($"ABC{Field1.ToString()}"); }
}
}
Wrapper that call the MongoDb layer
public class TaskService<T> : ITaskService<T> where T : ITask
{
private readonly IPersistanceLayer<ObjectId, object> _pl;
public async Task<T> GetNextTask(string key)
{
var oee = _pl.Mongo.Filter<T>(x => x.ConcurrencyKey==key
, typeof(T).Name).OrderBy(x=> x.Timestamp).FirstOrDefault();
return oee;
}
}
MongoDb Layer
public IEnumerable<T> Filter<T>(System.Linq.Expressions.Expression<Func<T, bool>> lambda, string collection)
{
var filter = Builders<T>.Filter.Where(lambda);
return _db.GetCollection<T>(collection).Find(filter).ToList();
}
The error I get is
[ERR] {document}.ComputedField is not supported.
In the collection i see the document saved when I insert it but and the value of the computed filed is stored correctly, the only problem is when i try to query on that field
The problem was that I was looking in the wrong collection and casting to the wrong class
public class TaskService<T> : ITaskService<T> where T : ITask
{
private readonly IPersistanceLayer<ObjectId, object> _pl;
public async Task<T> GetNextTask(string key)
{
var nextTask= _pl.Mongo.Filter<T>(x => x.ConcurrencyKey==key
, typeof(T).Name).OrderBy(x=> x.Timestamp).FirstOrDefault();
return nextTask;
}
}
In this method T was of the type BaseTask and not MyTask so my computed field was not there, I have corrected that and now it works
I want to map one table to two unrelated entities: EntityBasic and EntityAdvanced.
EntityAdvanced has extra business logic that I don't need for this one feature, and I would like to make a new Entity that only has fields from the table.
MyTable:
MyTableId : Guid
ParentId : Guid
Name : string
Description : string
Type : int
EntityBasic:
[Table("MyTable")]
public class EntityBasic
{
[Key]
public Guid MyTableId { get; set; }
public Guid ParentId { get; set }
public string Name { get; set; }
public string Description { get; set; }
public int Type { get; set; }
[ForeignKey("ParentId")]
public virtual List<EntityBasic> Entities{ get; set; }
}
EntityAdvanced:
[Table("MyTable")]
public class EntityAdvanced
{
private List<EntityAdvanced> _entities;
private List<Filter> _filters;
[Key]
public Guid MyTableId { get; set; }
public Guid ParentId { get; set }
public string Name { get; set; }
public string Description { get; set; }
public int Type { get; set; }
[ForeignKey("ParentId")]
public virtual List<EntityAdvanced> Entities
{
get { //Some complicated getter }
set { //Some complicated setter }
}
[NotMapped]
public string ImageUrl
{
get { //Some complicated getter }
set { //Some complicated setter }
}
public void SetFilters(//Some parameters)
{
//Some logic
}
}
When I do this i get this error:
The entity types 'EntityAdvanced' and 'EntityBasic' cannot share table 'MyTable' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them.
Is there a way to do what I want?
As a base start, your EntityAdvanced should inherit EntityBasic since they share the same base set of properties. You don't need to rewrite them. Note the extends EntityBasic.
[Table("MyTable")]
public class EntityBasic
{
[Key]
public Guid MyTableId { get; set; }
public Guid ParentId { get; set }
public string Name { get; set; }
public string Description { get; set; }
public int Type { get; set; }
[ForeignKey("ParentId")]
public virtual List<EntityBasic> Entities{ get; set; }
}
[NotMapped]
public class EntityAdvanced : EntityBasic
{
//[NotMapped]
public string ImageUrl
{
get { //Some complicated getter }
set { //Some complicated setter }
}
public void SetFilters(//Some parameters)
{
//Some logic
}
}
Using inheritence, List<EntityBasic> Entities could reference EntityAdvanced objects so you don't need anymore to declare:
[ForeignKey("ParentId")]
public virtual List<EntityAdvanced> Entities
{
get { //Some complicated getter }
set { //Some complicated setter }
}
You can get usefull information about implementing inheritence with Entity Framework here.
Happy coding!
I think you can use the ability "Table Splitting" of Entity Framework 6,
Have a look at the example here: https://www.c-sharpcorner.com/UploadFile/ff2f08/table-splitting-in-entity-framework-6-code-first-approach/
My goal is to create the poco classes without knowing which ORM is going to be used.
Now observe the following code...
public class NeuralModel
{
public NeuralModel()
{
Configurations = new HashSet<NeuralModelConfiguration>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTime? LastTrained { get; set; }
//Navigation properties
public ICollection<NeuralModelConfiguration> Configurations { get; set; }
//NotMapped properties
[NotMapped]
public NeuralModelConfiguration DefaultConfiguration { get { return Configurations.SingleOrDefault(config => config.IsDefault); } }
[NotMapped]
public bool IsTrained { get { return LastTrained.HasValue; } }
}
public class NeuralModelConfiguration
{
public NeuralModelConfiguration()
{
KeyValues = new HashSet<KeyValuePair<string, string>>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsDefault { get; set; }
public ICollection<KeyValuePair<string, string>> KeyValues
public int ModelId { get; set; }
//Navigation properties
public NeuralModel Model { get; set; }
}
Now suppose if I were to use Entity Framework Core, I get into the issue of mapping complex types (in my example it would be ICollection<KeyValuePair<string, string>>).
According to my research I came across two possible solutions:
Serialization
Another Entity
Now my question is that is there a third solution that do not require me to change my poco classes but rather do some sort of hidden processing at the dbcontext level?
Should there not be a third solution then out of the 2 available solutions which one would be considered better in terms of performance?
Following is the api call that return the Agent object
[Route("GetAgentById")]
public Agent GetAgentById(int id)
{
//Restrict Class fields
return new Agent(id);
}
Agent class have a lot of fields (Let say 100 fields)
public class Agent
{
public int AgentId { get; set; }
public string AgentName { get; set; }
public bool IsAssigned { get; set; }
public bool IsLoggedIn { get; set; }
......
......
public Agent() { }
}
Is there a way to ignore class properties without using annotations. I just want to return some of the fields of agent object before returning the agent object from api call. Is there any way to doing this
Return anonymous object with just required properties, like:
return new { agent.AgentId, agent.AgentName }
or use DTOs (which would be architecturally more correct, specially if you're building complex solution), in this example with Automapper:
return Mapper.Map<AgentDTO>(agent);
But if you really want to use "opt-out" approach and serialize just small subset of your object, and if you're using JSON.NET, you can mark just properties which needs to be serialized:
[DataContract]
public class Agent
{
// included in JSON
[DataMember]
public int AgentId { get; set; }
[DataMember]
public string AgentName { get; set; }
// ignored
public bool IsAssigned { get; set; }
public bool IsLoggedIn { get; set; }
}
Is it possible to use generic support with single table inheritance, and still be able to FindAll of the base class?
As a bonus question, will I be able to use ActiveRecordLinqBase<> as well? I do love those queries.
More detail:
Say I have the following classes defined:
public interface ICompany
{
int ID { get; set; }
string Name { get; set; }
}
[ActiveRecord("companies",
DiscriminatorColumn="type",
DiscriminatorType="String",
DiscriminatorValue="NA")]
public abstract class Company<T> : ActiveRecordBase<T>, ICompany
{
[PrimaryKey]
private int Id { get; set; }
[Property]
public String Name { get; set; }
}
[ActiveRecord(DiscriminatorValue="firm")]
public class Firm : Company<Firm>
{
[Property]
public string Description { get; set; }
}
[ActiveRecord(DiscriminatorValue="client")]
public class Client : Company<Client>
{
[Property]
public int ChargeRate { get; set; }
}
This works fine for most cases. I can do things like:
var x = Client.FindAll();
But sometimes I want all of the companies. If I was not using generics I could do:
var x = (Company[]) FindAll(Company);
Client a = (Client)x[0];
Firm b = (Firm)x[1];
Is there a way to write a FindAll that returns an array of ICompany's that can then be typecast into their respective types?
Something like:
var x = (ICompany[]) FindAll(Company<ICompany>);
Client a = (Client)x[0];
Or maybe I am going about implementing the generic support all wrong?
How about this:
[ActiveRecord("companies",
DiscriminatorColumn="type",
DiscriminatorType="String",
DiscriminatorValue="NA")]
public abstract class Company : ActiveRecordBase<Company>, ICompany {
[PrimaryKey]
private virtual int Id { get; set; }
[Property]
public virtual String Name { get; set; }
}
[ActiveRecord(DiscriminatorValue="firm")]
public class Firm : Company {
[Property]
public virtual string Description { get; set; }
}
[ActiveRecord(DiscriminatorValue="client")]
public class Client : Company {
[Property]
public virtual int ChargeRate { get; set; }
}
var allClients = ActiveRecordMediator<Client>.FindAll();
var allCompanies = ActiveRecordMediator<Company>.FindAll(); // Gets all Companies (Firms and Clients). Same as Company.FindAll();
Note that you can't just downcast your Companies as Clients or Firms, you need to use proper polymorphism or a visitor. See this for an explanation.