I'm trying to create an app just for learing purposes.
I'd Like to dynamically save any object to the right context.
So my idea is something like this:
My businessmodel for the player is this:
[Table]
public class PLAYER:ISiedlerEntity
{
[Column(CanBeNull = false, IsPrimaryKey = true, DbType = "INT NOT NULL Identity", IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public long ID { get; set; }
[Column]
public string Name { get; set; }
[Column]
public int GamesPlayed { get; set; }
}
}
The context is this:
public class PLAYERS:DataContext
{
private const string CONNECTION_STRING = "isostore:/tblPLAYERs.sdf";
public Table<PLAYER> Entities;
public PLAYERS()
: base(CONNECTION_STRING)
{
}
}
Do you think there is a possibility to handle the saving in one function just by passing the ISiedlerEntitiy?
My approach so far:
public static bool Save(ISiedlerEntity entity)
{
bool result = true;
string dcName = entity.GetType().Name + "S";
PropertyInfo pi = CurrentApp.GetType().GetProperty(dcName);
DataContext dc = pi.GetValue(CurrentApp) as DataContext;
foreach (var prop in dc.GetType().GetProperties())
{
if (prop.Name == "Entities")
{
var t = prop.GetValue(dc);
}
}
return result;
}
So far so fine, but now I need to cast the datacontext to the specified context, to access the Entities property.
Do you think this is possible so far? Or is there a easier solution?
Thanks and a good evening to everybody.
Matthias Müller
Related
The propblem: There is no "Name" field in the object or csv file, yet CsVHelper keeps looking for "Name" in the header. So why is it tripping there and what are some fixes?
When trying to build objects from a csv file, the following error comes up:
CsvHelper.HeaderValidationException: Header with name 'Name' was not found. If you are expecting some headers to be missing and want to ignore this validation, set the configuration HeaderValidated to null. You can also change the functionality to do something else, like logging the issue.
at CsvHelper.Configuration.ConfigurationFunctions.HeaderValidated(Boolean isValid, String[] headerNames, Int32 headerNameIndex, ReadingContext context)
I have tried setting HeaderValidated to null, but got the same results.
The header of the csv:
Id|Title|Description|AssignedToUserId|SourceUserId|DateCreated|DateAssigned|DateCompleted|Notes
The parsing code:
private static IEnumerable<T> GetCSVData<T>(string fullFileName)
{
PrintMembers<T>();
using (var reader = new StreamReader(fullFileName))
{
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.HasHeaderRecord = true;
csv.Configuration.IncludePrivateMembers = false;
csv.Parser.Configuration.Delimiter = "|";
var records = csv.GetRecords<T>().ToList();
return records;
}
}
}
A quick function for listing the public properties and fields of the class (T) being passed in outputs the following:
Properties...
Id
AssignedToUserId
SourceUserId
Title
Description
AssignedTo
Source
DateCreated
DateAssigned
DateCompleted
RelatedTasks
Notes
Fields...
[None]
They all have getters and setters.
EDIT
The IntermediateTask is the generic being fed into GetCSVData(). It has a default constructor. IntermediateTask is internal, but is in the same assembly as GetCSVData().
Code for the class(es) in question:
internal class IntermediateTask : Task
{
private int _Id;
new public int Id
{
get { return _Id; }
set { _Id = value; }
}
private int _AssignedToUserId;
public int AssignedToUserId
{
get { return _AssignedToUserId; }
set
{
_AssignedToUserId = value;
base.AssignedTo = userManager.Get(_AssignedToUserId);
}
}
private int _SourceUserId;
public int SourceUserId
{
get { return _SourceUserId; }
set
{
this._SourceUserId = value;
base.Source = userManager.Get(_SourceUserId);
}
}
public IntermediateTask() : base("", "", new IntermediateUser(), new IntermediateUser())
{
}
}
public class Task
{
public Task(string title, string description, User assignedTo, User source, DateTime? dateCreated = null, int id = 0)
{
this.RelatedTasks = new List<Task>();
this.Title = title;
this.Description = description;
this.AssignedTo = assignedTo;
this.Source = source;
this.DateCreated = dateCreated ?? DateTime.Now;
this.Id = id;
}
private int _Id;
public int Id
{
get { return _Id; }
protected set { _Id = value; }
}
public string Title { get; set; }
public string Description { get; set; }
public User AssignedTo { get; set; }
public User Source { get; set; }
public DateTime DateCreated { get; set; }
public DateTime? DateAssigned { get; set; }
public DateTime? DateCompleted { get; set; }
public IList<Task> RelatedTasks { get; set; }
public string Notes { get; set; }
override public string ToString()
{
return $"Id: {Id}; Title: {Title}";
}
}
In my case it complained about AssignedTo missing, but that is actually a property in the class that is not in the csv, so I had to add these two lines to make it work:
csv.Configuration.HeaderValidated = null;
csv.Configuration.MissingFieldFound = null;
I don't know why it would come up with 'Name' unless you have something different.
as the question title says, I am trying to map a custom object to a db column on windows phone how can I do this? the exception I am getting: "Unable to determine SQL type for 'Layer'."
layer is a custom object, what is the correct way to store this, can someone please provide me with a example. thank you
code:
...
[Table]
public class Product : INotifyPropertyChanged, INotifyPropertyChanging
{
#region ID
//not autogenerated, this is from the client
private String _id;
[Column(IsPrimaryKey = true, IsDbGenerated = false, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
public String Id
{
get { return _id; }
set
{
if (_id != value)
{
NotifyPropertyChanging("id");
_id = value;
NotifyPropertyChanged("id");
}
}
}
#endregion
#region Product Layer
private Layer _productlayer;
[Column]
public Layer ProductLayer
{
get { return _productlayer; }
set
{
if (_productlayer != value)
{
NotifyPropertyChanging("ProductLayer");
_productlayer = value;
NotifyPropertyChanged("ProductLayer");
}
}
}
#endregion
....
public class Layer
{
public string name{ get; set; }
public string des { get; set; }
public string pos { get; set; }
}
I'm writing a wpf app. I have a local database (sqlCE) with two entity classes that correspond to different tables. The first one class is Account and the second one is Movements. There's a relationship one-to-many between the two tables: an account can have more movements.
Here is Account class:
[Table]
public class Account
{
.....other private fields...
private Int16 iDA;
private EntitySet<Movement> movements;
...other properties with column attribute....
//primary key
[Column(IsPrimaryKey = true, Storage="iDA", IsDbGenerated = true, AutoSync = AutoSync.OnInsert, DbType = "smallint")]
public Int16 IDA
{
get { return iDA; }
private set { iDA = value; }
}
//association
[Association(Storage = "movements", OtherKey = "IDA")]
public EntitySet<Movement> Movements
{
get { return movements; }
set { this.movements.Assign(value); }
}
public Account()
{
this.movements = new EntitySet<Movement>();
}
}
and here's Movement class:
[Table]
public class Movement
{
...other fields...
private Int16 iDA;
private int iDM;
private EntityRef<Account> myAcc;
//primary key
[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert, DbType = "int NOT NULL IDENTITY", Storage = "iDM")]
public int IDM
{
get { return iDM; }
set { iDM = value; }
}
//property links the two tables
[Column(DbType = "smallint", Storage="iDA", isPrimaryKey=true)]
public Int16 IDA
{
get { return iDA; }
set { iDA = value; }
}
//association
[Association(Storage = "myAcc", ThisKey = "IDA")]
public Account MyAccount
{
get { return this.myAcc.Entity; }
set { this.myAcc.Entity = value; }
}
......
public Movement()
{
this.myAcc = new EntityRef<Account>();
}
}
I define IDA property to link the two tables. After that I write datacontext class:
public class DataBase : DataContext
{
public Table<Account> AccountTable
{
get { return this.GetTable<Account>(); }
}
public Table<Movement> MovementTable
{
get { return this.GetTable<Movement>(); }
}
public DataBase(string connection) : base(connection) { }
}
In mainclass I create database, but when i try to populate it with an account object, I get a sql exception! I can insert data calling InsertOnSubmit(Account a) without problems, but when I call SubmitChanges() the program stops and the exception says "The column can not contain null values. [Column name = IDA, Table name = Account]".
Anyone can help me?
Try using DbType = "smallint not null identity" and CanBeNull = false parameters for the Column attribute of the IDA field.
I've solved my problem, changing in Int the IDA property in both classes and making some adjustment.
I have some problem with Emit mapper when I try to save in database properties.
In first I mapped this class (it work good):
[Serializable]
public class ProfileProperty
{
public string PropertyValue { get; set; }
public bool IsVisible { get; set; }
public ProfileProperty(string value, bool isVisible = true)
{
this.PropertyValue = value;
this.IsVisible = isVisible;
}
public ProfileProperty()
{
this.IsVisible = true;
}
}
I mapped here:
var mapper = ObjectMapperManager.DefaultInstance.GetMapper<PollmericaProfile, ProfileModel>();
ProfileModel prof = new ProfileModel();
if (x.User != null)
{
prof = mapper.Map(x);
}
But some of the requirements need not a string property. That's why I decided to write this:
[Serializable]
public class ProfileProperty
{
public object PropertyValue { get; set; }
public bool IsVisible { get; set; }
public ProfileProperty(object value, bool isVisible = true)
{
this.PropertyValue = value;
this.IsVisible = isVisible;
}
public ProfileProperty()
{
this.IsVisible = true;
}
public T GetValue<T>()
{
return (T)this.PropertyValue;
}
}
And all mapping is not worked =(
If you ccan, help me please. If you want I can provide the necessary information.
P.S. To be honest, I want to transfer to a string and back, so at least works
UPD: I tried without method public T GetValue<T>()... It works...
Sorry for this, but I find answer very quicly.
in mapping I must to write this:
var mapper = ObjectMapperManager
.DefaultInstance
.GetMapper<PollmericaProfile, ProfileModel>( new DefaultMapConfig()
.IgnoreMembers<PollmericaProfile, ProfileModel>(new string[] { "GetValue" }));
ProfileModel prof = new ProfileModel();
if (x.User != null)
{
prof = mapper.Map(x);
}
I am trying to send an anonymous object over a web service. Is there anyway I can do this without manually creating a class and casting it to that class? Currently its throwing an exception saying Anonymous object could not be serialized.
// Some code has been removed here to simplify the example.
[WebMethod(EnableSession = true)]
public Response GetPatientList() {
var patientList = from patient in ((User)Session["user"]).Practice.Patients
select new {
patientID = patient.PatientID,
status = patient.Active ? "Active" : "Inactive",
patientIdentifier = patient.PatientIdentifier,
physician = (patient.Physician.FirstName + " " + patient.Physician.LastName).Trim(),
lastModified = patient.Visits.Max(v => v.VisitDate)
};
return patientList;
}
Thanks in advance.
Edit: Here is an example of what I mean by manually creating a class to return and fill it with the anonymous object...
public class Result {
public bool success;
public bool loggedIn;
public string message;
}
public class PracticeInfoResult : Result {
public string practiceName;
public string address;
public string city;
public string state;
public string zipCode;
public string phone;
public string fax;
}
Anonymous type are meant to be used for simple projections of very loosely coupled data, used only within a method. If it makes sense for a web method to return data of a type, it really should be decently encapsulated. In other words, even if you can find a way to return an instance of an anonymous type from a web method, I strongly suggest you don't do it.
I would personally not create the classes with public fields either - use automatically implemented properties instead, so you can safely add more behaviour later if you need to.
Note that after you've created the "proper" type, your query expression only needs to change very, very slightly - just add the name of the type between new and { to use an object initializer.
Here is the code I wound up using.
[WebMethod(EnableSession = true)]
public PatientsResult GetPatientList(bool returnInactivePatients) {
if (!IsLoggedIn()) {
return new PatientsResult() {
Success = false,
LoggedIn = false,
Message = "Not logged in"
};
}
Func<IEnumerable<PatientResult>, IEnumerable<PatientResult>> filterActive =
patientList => returnInactivePatients ? patientList : patientList.Where(p => p.Status == "Active");
User u = (User)Session["user"];
return new PatientsResult() {
Success = true,
LoggedIn = true,
Message = "",
Patients = filterActive((from p in u.Practice.Patients
select new PatientResult() {
PhysicianID = p.PhysicianID,
Status = p.Active ? "Active" : "Inactive",
PatientIdentifier = p.PatientIdentifier,
PatientID = p.PatientID,
LastVisit = p.Visits.Count > 0 ? p.Visits.Max(v => v.VisitDate).ToShortDateString() : "",
Physician = (p.Physician == null ? "" : p.Physician.FirstName + " " + p.Physician == null ? "" : p.Physician.LastName).Trim(),
})).ToList<PatientResult>()
};
}
public class Result {
public bool Success { get; set; }
public bool LoggedIn { get; set; }
public string Message { get; set; }
}
public class PatientsResult : Result {
public List<PatientResult> Patients { get; set; }
}
public class PatientResult {
public int PatientID { get; set; }
public string Status { get; set; }
public string PatientIdentifier { get; set; }
public string Physician { get; set; }
public int? PhysicianID {get;set;}
public string LastVisit { get; set; }
}
}