I have a layer of Data like this to bring me all Admins:
public List<Datos_Admin> SelectAllAdmin()
{
return (from u in contexto.Datos_Admin select u).ToList() ;
}
In my layer of Entities have this:
public class EDatos_Admin
{
public int Id_Admin { get; set; }
public string User_Name { get; set; }
public char Password { get; set; }
public string Nombre { get; set; }
public string Ap_Paterno { get; set; }
public string Ap_Materno { get; set; }
public DateTime Fecha_Alta { get; set; }
public DateTime Fecha_Modificacion { get; set; }
public int UserAdmin_Modificacion { get; set; }
public bool Activo { get; set; }
public EDatos_Admin(int Id_Admin, string User_Name, char Password, string Nombre, string Ap_Paterno, string Ap_Materno, DateTime Fecha_Alta, DateTime Fecha_Modificacion, int UserAdmin_Modificacion, bool Activo)
{
this.Id_Admin = Id_Admin;
this.User_Name = User_Name;
this.Password = Password;
this.Nombre = Nombre;
this.Ap_Paterno = Ap_Paterno;
this.Ap_Materno = Ap_Materno;
this.Fecha_Alta = Fecha_Alta;
this.Fecha_Modificacion = Fecha_Modificacion;
this.UserAdmin_Modificacion = UserAdmin_Modificacion;
this.Activo = Activo;
}
public EDatos_Admin()
{
// TODO: Complete member initialization
}
}
And in my Bussines layer have this:
public EDatos_Admin SeleccionaAllDatos_Admin()
{
foreach (var n in contexto.SelectAllAdmin())
{
listDatosAdmin = new EDatos_Admin()
{
Id_Admin = n.Id_Admin,
User_Name = n.User_Name,
};
}
return listDatosAdmin;
}
In the datagridview only I want show me Id_Admin and User_Name but it doesn't. And when I review in debugging I can see the data but the datagridview doesn't work.
And I call the method SeleccionaAllDatos_Admin in my Bussines layer like this in the load form
dataGridView1.DataSource = new NDatos_Admin().SeleccionaAllDatos_Admin();
How can fixed?
Thanks
I am cluless, i dont know why my database its showing in the deafult connection in the database , I am programing in C# MVC4 asp.net using razor technology,
here is my UserAccountContext
public class UserAccountContext : DbContext
{
public UserAccountContext()
: base("DefaultConnection")
{
}
public DbSet<UserAccount> UserAccounts { get; set; }
// Methods...
public DbSet<UserProfile> UserProfiles { get; set; }
// Methods...
public IQueryable<UserAccount> GetAll()
{
IQueryable<UserAccount> query = this.UserAccounts;
return query;
}
public UserAccount GetSingle(string _UserName)
{
UserAccount Query = this.GetAll().FirstOrDefault(x => x.UserName == _UserName);
return Query;
}
public void Save(UserAccount _UserAccount)
{
if (_UserAccount.ID == 0)
{
this.UserAccounts.Add(_UserAccount);
this.SaveChanges();
}
else
{
this.SaveChanges();
}
}
}
And here is my UserAccount Model
public class UserAccount
{
// Attributes turns into fields in the database
// These attributes persist in the database
[Key]
public int ID { get; set; }
public int UserId { get; set; }
public string UserName { get; set; }
public string WhoVoted { get; set; }
public double NumberOfVotes { get; set; }
// The following attributes will not persist in the DB
public string UserErrorMessage = string.Empty; // Volatile Variable
// Methods...
public UserAccount() { } //Constructor... This is needed to create the DB Table
public UserAccount(int _UserId, string _UserName) // Other Constructor
{
this.ID = 0;
this.UserId = _UserId;
this.UserName = _UserName;
this.NumberOfVotes = 0.0;
this.WhoVoted = string.Empty;
}
}
I have everything, i dont know how to deal with the database , Lookking forward for any help. Thank you in advance!
I have a simple SQLite method which returns a class given two parameters - the type T and the parameter value to be searched
public T GetSingleObject<T>(string id) where T:IIdentity, new()
{
lock (dbLock)
{
using (var sqlCon = new SQLiteConnection(DBPath))
{
sqlCon.Execute(Constants.DBClauseSyncOff);
sqlCon.BeginTransaction();
string sql = string.Format("SELECT * FROM {0} WHERE id=\"{1}\"", GetName(typeof(T).ToString()), id);
var data = sqlCon.Query<T>(sql);
return data[0];
}
}
}
I also have another method that takes 3 parameters, T, the parameter to be seated and the value to search for
public T GetSingleObject<T>(string para, string val) where T:IIdentity, new()
{
lock (dbLock)
{
using (var sqlCon = new SQLiteConnection(DBPath))
{
sqlCon.Execute(Constants.DBClauseSyncOff);
sqlCon.BeginTransaction();
string sql = string.Format("SELECT * FROM {0} WHERE {1}=\"{2}\"", GetName(typeof(T).ToString()), para, val);
var data = sqlCon.Query<T>(sql).FirstOrDefault();
return data;
}
}
}
These methods work without an issue and return the values expected, but with one caveat - there is a single table which works fine when the phone has a connection, but not when it's in aeroplane mode. The table has nothing more in it than strings, doubles, ints, DateTime and bool values.
GetName is a simple method that removes the assembly bits and pieces and leave just the classname
private string GetName(string name)
{
var list = name.Split('.').ToList();
if (list.Count == 1)
return list[0];
var last = list[list.Count - 1];
return last;
}
I have tried every way I can think of to access this table - including a straight
sqlCon.ExecuteScalar<MyClass>("SELECT * FROM MyClass");
and nothing offline, perfect data online.
The class itself looks like this
using System;
using System.Runtime.Serialization;
using System.Collections.Generic;
using SQLite;
namespace Models
{
public class MyClass : IIdentity
{
[PrimaryKey]
public string id { get; set; }
public string home_id { get; set; }
public string username { get; set; }
public string password { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
public string email { get; set; }
public bool syncenabled { get; set; }
public string tradingname { get; set; }
public string address { get; set; }
public string town { get; set; }
public string state { get; set; }
public string country { get; set; }
public string securitystamp { get; set; }
public string password_question { get; set; }
public string password_answer { get; set; }
public string mobileServiceAuthenticationToken { get; set; }
public string providerUserKey { get; set; }
public string mobiledeviceid { get; set; }
public DateTime last_login { get; set; }
public DateTime __createdAt { get; set; }
public DateTime __updatedAt { get; set; }
public string user_type { get; set; }
public bool is_deleted { get; set; }
public bool account_enabled { get; set; }
public string subscription_id { get; set; }
[IgnoreDataMember, Ignore]
public List<MyUsers> UserModules { get { return AppDelegate.Self.DBManager.GetListOfObjects<MyUsers>("user_id", id); } }
public override string ToString()
{
return string.Format("[MyClasss: id={0}, home_id={1}, username={2}, password={3}, firstname={4}, lastname={5}, email={6}, syncenabled={7}, tradingname={8}, address={9}, town={10}, state={11}, country={12}, securitystamp={13}, password_question={14}, password_answer={15}, mobileServiceAuthenticationToken={16}, providerUserKey={17}, mobiledeviceid={18}, last_login={19}, __createdAt={20}, __updatedAt={21}, user_type={22}, is_deleted={23}, account_enabled={24}, subscription_id={25}, UserModules={26}]", id, home_id, username, password, firstname, lastname, email, syncenabled, tradingname, address, town, state, country, securitystamp, password_question, password_answer, mobileServiceAuthenticationToken, providerUserKey, mobiledeviceid, last_login, __createdAt, __updatedAt, user_type, is_deleted, account_enabled, subscription_id, UserModules);
}
}
Nothing in there that I can see should cause an issue when offline. The query always returns null offline, data online.
I am trying to refactor some old code and wanted to create more logical inheritance.
We have struct Custom Class which we have separated into (3) levels:
AccountView > Details > Full with inheritance. We set the properties of each one as needed.
After looking at the setters, we wanted to combine them into a single class 'SetAccountProp' with methods that set the properties.
We have the 'CustomerBaseView' where we pass in Models ACCOUNT data which works.
Now for the CustomerDetailView pass the same Model ACCOUNT data, but we would like to fill the properties of 'CustomerBaseView' use function 'CustomerBaseView' then fill the details.
Also, for CustomerFullView pass the Model ACCOUNT data, and fill the properties of 'CustomerBaseView' THEN 'CustomerBaseView' and then the remaining fields for CustomerFullView.
How can I call and fill the 'CustomerBaseView' within the 'CustomerDetailView' function? Do I initialize new AccountsView(); in each function?
Not sure how to finish up the refactor without repeating the:
// -- CustomView <--- replace with func?
view.Email = data.Email;
view.Active = data.Active;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
in the Details and Full functions.
CODE
namespace BLL.Presenters
{
public class AccountsView
{
public string Email { get; set; }
public bool Active { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Details : AccountsView
{
public bool Administrator { get; set; }
public DateTime? LastLogin { get; set; }
}
public class Full : Details
{
public Guid ID { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public string FullName { get; set; }
}
public class SetAccountProp
{
public static AccountsView CustomerBaseView(Account data)
{
var view = new AccountsView();
view.Email = data.Email;
view.Active = data.Active;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
return view;
}
public static Details CustomerDetailView(Account data)
{
var view = new Details();
// -- CustomView <--- replace with func?
view.Email = data.Email;
view.Active = data.Active;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
// -- Details
view.Administrator = data.Administrator;
view.LastLogin = data.LastLogin;
return view;
}
public static Full CustomerFullView(Account data)
{
var view = new Full();
// -- CustomView <--- replace with func?
view.Email = data.Email;
view.Active = data.Active;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
// -- Details <--- replace with func?
view.Administrator = data.Administrator;
view.LastLogin = data.LastLogin;
// -- Full
view.ID = data.ID;
view.Created = data.Created;
view.Modified = data.Modified;
view.FullName = data.LastName + ", " + data.FirstName;
return view;
}
}
}
Using constructor chaining, you could have something like this:
Each constructor calls it's base class' constructor first, so you don't have to repeat code.
namespace BLL.Presenters
{
using System;
public class Account // dummy to make it compile
{
public string Email;
public bool Active;
public string FirstName;
public string LastName;
public bool Administrator;
public DateTime? LastLogin;
public Guid ID;
public DateTime Created;
public DateTime Modified;
}
public class AccountsView
{
public string Email { get; set; }
public bool Active { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public AccountsView(Account data)
{
this.Email = data.Email;
this.Active = data.Active;
this.FirstName = data.FirstName;
this.LastName = data.LastName;
}
}
public class Details : AccountsView
{
public bool Administrator { get; set; }
public DateTime? LastLogin { get; set; }
public Details(Account data) : base(data)
{
this.Administrator = data.Administrator;
this.LastLogin = data.LastLogin;
}
}
public class Full : Details
{
public Guid ID { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public string FullName { get; set; }
public Full(Account data) : base(data)
{
this.ID = data.ID;
this.Created = data.Created;
this.Modified = data.Modified;
this.FullName = data.LastName + ", " + data.FirstName;
}
}
class Program
{
static void Main()
{
Console.WriteLine();
Console.ReadLine();
}
}
}
Why not something like this:
public class CustomerBase
{
public string Email { get; private set; }
public bool Active { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
protected void SetAccountInfo(Account account)
{
this.Email = account.Email;
this.Active = account.Active;
this.FirstName = account.FirstName;
this.LastName = account.LastName;
}
}
public class CustomerA : CustomerBase
{
public string IsAdmin { get; private set; }
public DateTime? LastLogin { get; private set; }
public void SetAccountInfo(Account account)
{
base.SetAccountInfo(account);
this.IsAdmin = account.IsAdmin;
this.LastLogin = account.LastLogin;
}
}
public class Account
{
//your properties
public string Email { get; set; }
public bool Active { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string IsAdmin { get; set; }
public DateTime? LastLogin { get; set; }
}
Or let the SetAccountInfo() return this
public CustomerA SetAccountInfo(Account account)
{
base.SetAccountInfo(account);
this.IsAdmin = account.IsAdmin;
this.LastLogin = account.LastLogin;
return this;
}
UPDATED: I understood I should not use a DbSet so I changed the implementation to an ICollection as suggested by Erenga
Please consider the following classes:
[Table("Tenant")]
public class Tenant : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
[Key]
public string Guid { get; set; }
public virtual ICollection<User> Users { get; set; }
}
[Table("User")]
public class User : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public string Password { get; set; }
}
The first test creates a new Tenant and a new User and stores them in the appropriate tables.
[Test]
public void CreateNewUserForNewTenant()
{
var user = _applicationContext.Users.Create();
user.Name = "barney";
user.EmailAddress = "barney#flinstone.com";
var tenant = _applicationContext.Tenants.Create();
tenant.Name = "localhost";
tenant.Guid = Guid.NewGuid().ToString();
tenant.Users.Add(user); // NullReferenceException, I expected the EF would LazyLoad the reference to Users?!
_tenantRepository.Add(tenant);
_applicationContext.SaveChanges();
}
This test will fail on a NullReferenceException since the property Users is not initialized.
How should I change my code that I can rely on LazyLoading provided with EF?
There are 2 problems I see here.
As #SimonWhitehead mentioned, reference types are initialized as null by default. Lazy loading works only on entities created by EF. These are actually sub classes of your class that contain addtional logic to lazy load.
DbSet is not a collection type that is supported on entities. You need to change the type to ICollection, ISet, or IList.
Here's a working example
[Table("Tenant")]
public class Tenant : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
[Key]
public string Guid { get; set; }
public virtual ICollection<User> Users { get; set; }
}
[Table("User")]
public class User : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public string Password { get; set; }
}
[Test]
public void CreateNewUserForNewTenant()
{
var user = _applicationContext.Users.Create();
user.Name = "barney";
user.EmailAddress = "barney#flinstone.com";
var tenant = _applicationContext.Tenents.Create();
tenant.Name = "localhost";
tenant.Guid = Guid.NewGuid().ToString();
tenant.Users = new List<User> { user };
_tenantRepository.Add(tenant);
_applicationContext.SaveChanges();
}
var tenant = new Tenant
{
Name = "localhost",
Guid = Guid.NewGuid().ToString(),
Users = new List<User> { user }
};
I think you were expecting something like this (not threadsafe):
[Table("Tenant")]
public class Tenant : IEntity
{
private DbSet<User> _users;
public int Id { get; set; }
public string Name { get; set; }
[Key]
public string Guid { get; set; }
public virtual ICollection<User> Users
{
get
{
if (_users == null)
_users = new List<Users>();
return _users;
}
set { _users = value; }
}
}
I'm sure the Lazy<T> class could be utilised somehow too but I am not familiar with that class.