Here is the class I'm trying to create.
I get the error 'DbMainContext does not contain a definition for tName' It's the 3rd line under the using statement below.
I don't want to have to keep recoding the query in a lot of places, so it seemed like a helper method would keep the code cleaner.
public class DbHelper
{
static string GetValueFromDatabase(DatabaseData dbData)
{
string tName = dbData.TableName;
using (DbMainContext db = new DbMainContext())
{
var query =
(from t in db.tName
where t.ID == 1198
select t.LastName).Single<String>();
return query;
}
}
}
public class DatabaseData : IDatabaseData
{
public string TableName { get; set; }
public string ColumnName { get; set; }
public string WhereClause { get; set; }
public int WhereId { get; set; }
}
public interface IDatabaseData
{
public string TableName { get; set; }
public string ColumnName { get; set; }
public string WhereClause { get; set; }
public int WhereId { get; set; }
}
}
You're perhaps looking for something like How to generalise access to DbSet members of a DbContext?.
You can't use db."Users", so you can't use db.tName either. You could use reflection for that, but you don't want that.
Related
I have question related to dynamic Linq.
I have a class structure defined as below.
public class UserProfile
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public long Overtime { get; set; }
public UserProfileDetails UserProfileDetails { get; set; }
}
public class UserProfileDetails
{
public UserProfileDetails()
{
LstString = new List<string>();
}
public string Department { get; set; }
public double Salary { get; set; }
public int LeaveBalance { get; set; }
public List<string> LstString { get; set; }
}
Created a object of UserProfile like given below.
var a = new UserProfile();
For a normal Linq I can execute the following. I am trying to find all the strings in UserProfileDetails while is not same a my first name.
var vvv = a.UserProfileDetails.LstString.Where(x => !x.Equals(a.FirstName)).ToList();
I want to convert the above linq to dynamic linq and used the following
var vDyna = a.UserProfileDetails.LstString.AsQueryable().Where("!Equals(FirstName)").ToList();
But the above is giving the error:
System.Linq.Dynamic.Core.Exceptions.ParseException: 'No property or field 'FirstName' exists in type 'String''.
Can anyone help me with this please?
I think it's similar to the LINQ function. In the where string you have to use the UserProfile variable a.
Your Code:
var vDyna = a.UserProfileDetails.LstString.AsQueryable().Where("!Equals(FirstName)").ToList();
My suggestion:
var vDyna = a.UserProfileDetails.LstString.AsQueryable().Where(s => !s.Equals(a.FirstName)).ToList();
I never used Dynamic Linq, but maybe that helps.
Source:
https://learn.microsoft.com/en-us/dotnet/api/system.linq.queryable.where?view=net-5.0
EDIT 1:
var vDyna = a.UserProfileDetails.LstString.AsQueryable().Where("!Equals(#0)", a.FirstName).ToList();
Am having my table as below , by the usage of Sqlite :
public class Medication
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string unique_id { get; set; }
public string username { get; set; }
public string insulin_type { get; set; }
public string units { get; set; }
public string status { get; set; }
public string alarm_time { get; set; }
public Medication() { }
}
Now I want to use IEnumerable to get a Column alarm_time List but I don't know how to get it. Below is my code for that:
public IEnumerable<Medication> AllMedicationResults()
{
return (from t in _connection.Table<Medication>()
select t).ToList();
}
How can I include the Column alarm_time in that code above.
In your select request only that property (and change method return type)
public IEnumerable<string> AllMedicationResults()
{
return (from t in _connection.Table<Medication>()
select t.alarm_time).ToList();
}
But IMO it will look cleaner to just use method syntax:
public IEnumerable<string> AllMedicationResults()
{
return _connection.Table<Medication>().Select(t => t.alarm_time).ToList();
}
Notice that as you are returning an IEnumerable<T> you might want to consider removing the ToList() and using the benefits of linq's deffered execution
Code without AutoMapper:
List<CountryDM> countryDMList = _countryRepo.GetCountry();
List<CountryVM> countryVMList = new List<CountryVM>();
foreach (CountryDM countryDM in countryDMList)
{
countryVMList.Add(CountryVM.ToViewModel(countryDM));
}
return countryVMList;
I used AutoMapper for the above task. But it returns a NULL list. Please refer the below code:
List<CountryDM> countryDMList = _countryRepo.GetCountry();
Mapper.CreateMap<List<CountryDM>, List<CountryVM>>();
List<CountryVM> countryVMList = new List<CountryVM>();
return Mapper.Map<List<CountryVM>>(countryDMList);
public class CountryDM
{
public int ID { get; set; }
public string CountryCode { get; set; }
public string Description { get; set; }
}
public class CountryVM
{
public int ID { get; set; }
public string CountryCode { get; set; }
public string Description { get; set; }
}
You don't need to define a mapping between lists, just between objects, AutoMapper will know how to extrapolate that:
Mapper.CreateMap<CountryDM, CountryVM>();
the rest stays the same
I have some classes which only serve to contain data. For example
public class EntityAdresse : IEntityADRESSE
{
public string Name1 { get; set; }
public string Strasse { get; set; }
public string Plz { get; set; }
public string Ort { get; set; }
public string NatelD { get; set; }
public string Mail { get; set; }
public int Id_anrede { get; set; }
public string Telefon { get; set; }
public int Id_adr { get; set; }
public int Cis_adr { get; set; }
}
This represents a address. Like I said, it only contains data. No Methods (I know the interface doesn't make sense here...)
Now I need to implement ToString for all this Entity-Classes and there are a lot of them.
My question is: Is there a metaprograming feature in C# which generates this tostring methods automaticaly? I don't want to write boiler plate code for every which of these classes.
Alternatively I could also write a perl or python script to generate the code. But I prefer doing it in C# directly.
Generally, you need to obtain all property values of your class and combine them into a single string. This can be done using the following approach:
public override string ToString()
{
PropertyDescriptorCollection coll = TypeDescriptor.GetProperties(this);
StringBuilder builder = new StringBuilder();
foreach(PropertyDescriptor pd in coll)
{
builder.Append(string.Format("{0} : {1}", pd.Name , pd.GetValue(this).ToString()));
}
return builder.ToString();
}
The feature is called reflection. A simplest example would be:
public class EntityBase
{
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach ( var property in this.GetType().GetProperties() )
{
sb.Append( property.GetValue( this, null ) );
}
return sb.ToString();
}
}
public class TheEntity : EntityBase
{
public string Foo { get; set; }
public string Bar { get; set; }
}
Please finetune it to fulfill your requirements.
As you can see the idea is to have a single implementation in a base class so that all descendands automatically inherit the same behavior.
A short version of what's already been said:
public override string ToString()
{
var propertyStrings = from prop in GetType().GetProperties()
select $"{prop.Name}={prop.GetValue(this)}";
return string.Join(", ", propertyStrings);
}
There isn't a feature built into the language to do this automatically, but you could write a library to do it using the Expression features in the framework to generate a function to do it.
You'd have a function like this:
Func<T,string> GenerateToString<T>()
And in your class you have something like this:
public class EntityAdresse : IEntityADRESSE
{
private static readonly Func<EntityAdresse,string> s_ToString=Generator.GenerateToString<EntityAdresse>();
public string Name1 { get; set; }
public string Strasse { get; set; }
public string Plz { get; set; }
public string Ort { get; set; }
public string NatelD { get; set; }
public string Mail { get; set; }
public int Id_anrede { get; set; }
public string Telefon { get; set; }
public int Id_adr { get; set; }
public int Cis_adr { get; set; }
public override ToString()
{
return s_ToString(this);
}
}
The challenge is writing GenerateToString. Using the Expression framework and reflection you'll be able to create a delegate that is as efficient as if you'd written the code by hand.
You could use reflection on it's own, but the performance hit will soon start to be an issue.
There is an open source framework StatePrinter for automatic ToString generation. It is very configurable so it should cater for your needs. The introspection code can be found at Introspection
I have a Model like this
public class Challenge
{
public int ID { get; set; }
public string Name { get; set; }
public string Blurb { get; set; }
public int Points { get; set; }
public string Category { get; set; }
public string Flag { get; set; }
public List<string> SolvedBy { get; set; }
}
public class ChallengeDBContext : DbContext
{
public DbSet<Challenge> Challenges { get; set; }
}
and then Controller like this. But I cannot update the List "SolvedBy", the next time I step through with the debugger, the list is still empty.
[HttpPost]
public string Index(string flag = "", int id=0)
{
Challenge challenge = db.Challenges.Find(id);
if (flag == challenge.Flag)
{
var chall = db.Challenges.Find(id);
if (chall.SolvedBy == null)
{
chall.SolvedBy = new List<string>();
}
chall.SolvedBy.Add(User.Identity.Name);
db.Entry(chall).State = EntityState.Modified;
db.SaveChanges();
//congrats, you solved the puzzle
return "got it";
}
else
{
return "fail";
}
}
is there any way around it to make a list of strings kept in the database?
EF don't know how to store an array in database table so it just ignore it. You can create another table/entity or use XML/JSON to store the list. You can serialize the list before saving and deserialize it after loading from database
A List<T> in a model would normally map to a second table, but in your DbContext you only have a single table. Try adding a second table.
public class ChallengeDBContext : DbContext
{
public DbSet<Challenge> Challenges { get; set; }
public DbSet<Solution> Solutions {get; set;}
}
public class Challenge
{
public int ID { get; set; }
public string Name { get; set; }
public string Blurb { get; set; }
public int Points { get; set; }
public string Category { get; set; }
public string Flag { get; set; }
public List<Solution> SolvedBy { get; set; }
}
public class Solution
{
public int ID { get; set; }
public string Name { get; set; }
}
Then your controller can use code along the lines of...
var chall = db.Challenges.Find(id);
if (chall.SolvedBy == null)
{
chall.SolvedBy = new List<Solution>();
}
chall.SolvedBy.Add(new Solution {Name=User.Identity.Name});
None of the above has been tested and I may have made some mistakes there, but the general principle I want to illustrate is the fact that you need another table. The List<T> represents a JOIN in SQL.