InsertOnSubmit method throws NullReferenceException ... Linq to sql C# entity/DataContext class - linq-to-sql

Here's my DataContext class:
public class Dealer : DataContext
{
public Table<Vehicle> Vehicles;
public Table<Customer> Customers => GetTable<Customer>();
public Table<Account> Accounts;
public Table<Transaction> Transactions;
public Dealer(string connection) : base(connection) { }
}
Here's the Customer Class:
[Table(Name="Customers")]
public class Customer
{
[Column(IsPrimaryKey = true, DbType = "int NOT NULL IDENTITY", IsDbGenerated = true, CanBeNull = false)]
public int CustomerID { get; set; }
[Column(CanBeNull = false)]
public string FirstName { get; set; }
[Column(CanBeNull = false)]
public string LastName { get; set; }
[Column(CanBeNull = false)]
public string SSN { get; set; }
public override string ToString()
{
return string.Concat(this.FirstName, " ", this.LastName, " ", this.SSN);
}
private EntitySet<Vehicle> vehicles = null;
[Association(Storage = "vehicles", OtherKey = "CustomerID", ThisKey = "CustomerID")]
public EntitySet<Vehicle> Vehicles { get; set; }
//implement INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Here's the code that throws the NullReferenceException:
private void Button_Click(object sender, RoutedEventArgs e)
{
Customer c = new Customer() { FirstName="John", LastName="Smith", SSN = "123456" };
Dealer d = new Dealer(App.connectionString);
d.Customers.InsertOnSubmit(c); //d.Customers is null and throws null reference exception.!!!
try
{
d.SubmitChanges();
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
I have googled for many hours now and I can't figure out why it's throwing NullReferenceException... (found a lot of other posts but non of the solutions seem to work for me )
Please help ...
Thanks in advance.

I had the same problem yesterday. Removing getters and setters from DataContext class helped. By the way I'd change CustomerId column property by addingAutoSync=Autosync.OnInsert

Related

linq2db insert or query is returning error: Connection option 'datasource' is duplicated

I have a simple table which I can perform Inser and Read operations using MySQL Commands.
For some reason, when using Linq2DB I get the following ERROR:
Connection option 'datasource' is duplicated.
at MySql.Data.MySqlClient.MySqlBaseConnectionStringBuilder.AnalyzeConnectionString
This Works:
private void BulkInsert(List<string> rows)
{
var commandText = new StringBuilder("INSERT INTO cloudevents (JobId, Name, ErrorUrgency, EventCategory, EventType, Time, Parameters) VALUES ");
commandText.Append(string.Join(",", rows));
commandText.Append(";");
try
{
using (MySqlCommand command = MySqlConnectionConnector.CreateCommand())
{
command.CommandText = commandText.ToString();
command.CommandType = CommandType.Text;
command.ExecuteNonQuery();
}
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e);
throw;
}
finally
{
rows.Clear();
}
}
This Throw Error:
using (var db = new EocIpcDB())
{
db.Insert(new EventsOnCloudData()
{
JobId = 2000,
ErrorUrgency = "Error",
EventCategory = "HW",
EventType = "Disk",
Name = "Haedware Events",
Time = DateTime.Now,
Parameters = "Lots of Parameters"
});
var query = from p in db.EventsOnCloudData select p;
return query.ToList();
}
My Data Table:
[Table("cloudevents")]
public class EventsOnCloudData
{
[PrimaryKey, Identity]
public int Key { get; set; } // primary key / uid
[Column(Name = "Name"), NotNull]
public string Name { get; set; }
[Column(Name = "ErrorUrgency"), NotNull]
public string ErrorUrgency { get; set; }
[Column(Name = "EventCategory"), NotNull]
public string EventCategory { get; set; }
[Column(Name = "EventType"), NotNull]
public string EventType { get; set; }
[Column(Name = "JobId"), NotNull]
public int JobId { get; set; }
[Column(Name = "Time"), NotNull]
public DateTime Time { get; set; } //UTC
[Column(Name = "Parameters"), NotNull]
public string Parameters { get; set; } //JSON Parameters
}
LinqtoDB Data Connection Class:
public class EocIpcDB : LinqToDB.Data.DataConnection
{
public EocIpcDB() : base("eocipcdb") { }
public ITable<EventsOnCloudData> EventsOnCloudData => GetTable<EventsOnCloudData>();
}
Linq 2 DB settings Class:
public class EventsOnCloudSettings : ILinqToDBSettings
{
public IEnumerable<IDataProviderSettings> DataProviders => Enumerable.Empty<IDataProviderSettings>();
public string DefaultConfiguration => "SqlServer";
public string DefaultDataProvider => "SqlServer";
public IEnumerable<IConnectionStringSettings> ConnectionStrings
{
get
{
yield return
new ConnectionStringSettings
{
Name = "eocipcdb",
ProviderName = ProviderName.MySql,
ConnectionString = #"Server=.\;datasource=localhost;port=3306;database=eocipcdb;username=root;password=HPdfeHPdfe#1;"
};
}
}
}
internal class ConnectionStringSettings : IConnectionStringSettings
{
public string Name { get; set; }
public string ProviderName { get; set; }
public string ConnectionString { get; set; }
public bool IsGlobal => false;
}
This error generated by MySql.Data provider itself because you have server option set twice: Server=.\;datasource=localhost;. Server and Data Source are synonyms, alongside with host, data source, address, addr and network address

Error while storing a list of custom object in isolated storage

I have a custom class of the following type
[Table]
class MyApp
{
public MyApp()
: base()
{
}
[Column(IsPrimaryKey=true, UpdateCheck = UpdateCheck.Never)]
public string appCode { get; set; }
[Column(UpdateCheck = UpdateCheck.Never)]
public string procCode { get; set; }
}
I have another class which contains a list of MyApp objects which is as below:
[Table]
class ApplicationUser
{
public ApplicationUser()
:base()
{
}
[Column(IsPrimaryKey = true, UpdateCheck = UpdateCheck.Never)]
public string userId { get; set; }
[Column(UpdateCheck = UpdateCheck.Never)]
public List<MyApp> applicationList { get; set; }
}
While calling the CreateDatabase() method in my DataContext class i get the following error:
Unable to determine SQL type for 'System.Collections.Generic.List`1[XCell.Framework.data.MyApp]'
Please guide me on this.
As I see the problem is that the applicationList is marked with the Column attribute, though it represents a relation.
Basically you will have to correctly map the relation between those entities using EntityRef<T> and EntitySet<T> classes and the Association attribute.
This article may be helpful.
The example with the corrected mapping (for one-to-many relation) below:
Adjusted ApplicationUser class
[Table]
public class ApplicationUser
{
private EntitySet<MyApp> _userApplications = new EntitySet<MyApp>();
[Column(IsPrimaryKey = true, UpdateCheck = UpdateCheck.Never)]
public string UserId { get; set; }
[Association(Storage = "_userApplications", ThisKey = "UserId", OtherKey = "ApplicationUserId")]
public EntitySet<MyApp> ApplicationList
{
get { return _userApplications; }
set { _userApplications = value; }
}
}
And the adjusted MyApp class
[Table]
public class MyApp
{
private EntityRef<ApplicationUser> _applicationUserRef;
[Column(IsPrimaryKey = true, UpdateCheck = UpdateCheck.Never)]
public string AppCode { get; set; }
[Column(UpdateCheck = UpdateCheck.Never)]
public string ProcCode { get; set; }
[Column]
public string ApplicationUserId { get; set; }
[Association(Name = "FK_MyApp_ApplicationUser", Storage = "_applicationUserRef", ThisKey = "ApplicationUserId", OtherKey = "UserId")]
public ApplicationUser ApplicationUserReference
{
get { return _applicationUserRef.Entity; }
set { _applicationUserRef.Entity = value; }
}
}

Storing Variable in When Tombstone Occurs

How can i store the variables in savestate() method of TombstoneHelper class to avoid Tombstone in windows phone 8.
I think you can try to use PhoneApplicationService.State Property - it works like Dictionary(string, object). MSDN
To save on Deactivated event:
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
int myObject = 5;
PhoneApplicationService.Current.State.Add("myName", myObject);
}
To restore on Activated event:
private void Application_Activated(object sender, ActivatedEventArgs e)
{
var returnedOnject = PhoneApplicationService.Current.State["myName"];
}
Thanks Man +1 For your comment Romasz .It is now working but there is an error when app went to the tombstone stage because PhoneApplicationService State is null when your app comes from the Tombstone Stage.So i stored that phoneState in the isolated storage in application_Deactivated and retrieve from isolated Storage in application_activated.
I made simple LoginData Class where i can store my data that i have to preserving.
[DataContract]
public class LoginData
{
[DataMember]
public string Username { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public int EstablishmentId { get; set; }
[DataMember]
public bool chainmanager { get; set; }
[DataMember]
public string logoimage { get; set; }
public LoginData(string username, string password, int establishmentId, bool ischainmager,string logoimage)
{
this.Username = username;
this.Password = password;
this.EstablishmentId = establishmentId;
this.chainmanager = ischainmager;
this.logoimage = logoimage;
}
}
Then make method to save the Class object in app.xml
public void save(LoginData ld)
{
PhoneApplicationService phonestate = PhoneApplicationService.Current;
phonestate.State["_lOGINcREDENTIALs_"]= ld;
var settings = IsolatedStorageSettings.ApplicationSettings;
settings["Credatials"] = phonestate.State["_lOGINcREDENTIALs_"];
}
And Method to load the Class object
public void load()
{
PhoneApplicationService phonestate = PhoneApplicationService.Current;
var settings = IsolatedStorageSettings.ApplicationSettings;
object credentials;
if (settings.TryGetValue("Credatials", out credentials))
{
phonestate.State["_lOGINcREDENTIALs_"]= credentials;
}
}
and call these methods in various event like
private void Application_Launching(object sender, LaunchingEventArgs e)
{
load();
}
private void Application_Activated(object sender, ActivatedEventArgs e)
{
load();
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
save();
}
private void Application_Closing(object sender, ClosingEventArgs e)
{
save();
}

wp8 DataBase doesn't work~

I want use a database in my app, but there are some errors:
An exception of type 'System.Data.SqlServerCe.SqlCeException' occurred in Microsoft.Phone.Data.Internal.ni.dll but was not handled in user code
If there is a handler for this exception, the program may be safely
continued.
It occurs on this:
if (true == db.PersonData.Any())
and
db.PersonData.InsertOnSubmit(newData);
The code worked on wp7....how do you fix it?
Thx~
[Table]
public class CPersonData
{
[Column]
public string Lat { get; set; }
[Column]
public string Lon { get; set; }
[Column]
public string SelectShopType { get; set; }
[Column]
public DateTime UpdateTime { get; set; }
}
public class DataBase : DataContext
{
public Table<CPersonData> PersonData;
public DataBase(string strConnection) : base(strConnection)
{
if (false == this.DatabaseExists())
this.CreateDatabase();
}
}
using (var db = new DataBase("Data Source=isostore:/FindTea.sdf"))
{
CPersonData newData = new CPersonData();
newData.Lat = "";
newData.Lon = "";
newData.SelectShopType = "1,2,3";
db.PersonData.InsertOnSubmit(newData);
db.SubmitChanges();
}
I found the problem!!!I didn't put a primary key in this table, so when I add this
[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", AutoSync = AutoSync.OnInsert, CanBeNull = false)]
public int ID { get; set; }
The App doesn't crash!!!!

Entity Framework type case generic in predicate

I am working on updating to a more manageable repository pattern in my MVC 4 project that uses Entity Framework code first. I've integrated a generic base repository class that will do basic CRUD operations so I don't have to implement these in each repository I create. I have ran into an issue where my All method needs to filter there query by a deleted flag if the entity is a type of TrackableEntity. Since the Entity is generic in the base repository I am attempting to cast is to a type of TrackableEntity in the where which just results in the following error message.
The 'TypeAs' expression with an input of type 'NameSpace.Models.ClientFormField' and a check of type 'NameSpace.Models.TrackableEntity' is not supported. Only entity types and complex types are supported in LINQ to Entities queries.
This error makes complete since and I understand why the code I have is not working but I am trying to find a way to filter out deleted items without having to override this method in all of my repositories. The code I have for my All method is below.
public virtual IEnumerable<T> All()
{
if (typeof(T).IsSubclassOf(typeof(TrackableEntity)))
return dbSet.Where(e => !(e as TrackableEntity).IsDeleted).ToList();
return dbSet.ToList();
}
I know that I can do the following
public virtual IEnumerable<T> All(Expression<Func<T, bool>> predicate = null)
{
if (predicate != null)
return dbSet.Where(predicate).IsDeleted).ToList();
return dbSet.ToList();
}
And then add this to all of my repositories
public override IEnumerable<CaseType> All(Expression<Func<CaseType,bool>> predicate = null)
{
if (predicate == null)
predicate = e => !e.IsDeleted;
return base.All(predicate);
}
The problem I have with this is that I am duplicating code, this is basically a copy and paste into all of my repositories which defeats the purpose of changing to this new repository pattern. I made the switch to end duplicated code in my repositories.
Here is an example of one of my entities.
public class CaseType : TrackableEntity, IValidatableObject
{
public int Id { get; set; }
public string Name { get; set; }
public bool InUse { get; set; }
public bool IsValid { get { return !this.Validate(null).Any(); } }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (String.IsNullOrEmpty(Name))
yield return new ValidationResult("Case Type name cannot be blank", new[] { "Name" });
//Finish Validation Rules
}
}
And the TrackableEntity
public abstract class TrackableEntity
{
public bool Active { get; set; }
public bool IsDeleted { get; set; }
public virtual User CreatedBy { get; set; }
public virtual User ModifiedBy { get; set; }
public DateTime DateCreated { get; set; }
public DateTime DateModified { get; set; }
}
Any help on this would be much appreciated.
I finally got a solution working that I am happy with. I ended up making 2 generic repositories. One that is the base repository which deals with all of the calls to the database for my BaseEntity which all entities inherit from. Then I made my 2nd generic repo which is inherits BaesEntity and overrides a few methods to handle the needs of my TrackableEntities. In the end this does what I want by handling the filtering of soft deleted items from within the repo and also gives me more flexibility with the TrackableEntity.
BaseRepository -
public class BaseRepository<T> : IBaseRepository<T> where T : BaseEntity
{
private readonly IAppDb _db;
private readonly IDbSet<T> _dbSet;
public BaseRepository(IAppDb db)
{
_db = db;
_dbSet = Lwdb.Set<T>();
}
protected IAppDb Lwdb
{
get { return _db; }
}
#region IBaseRepository<T> Members
public virtual T GetById(int id)
{
return _dbSet.Find(id);
}
public virtual T Add(T entity)
{
_dbSet.Add(entity);
_db.Commit();
return entity;
}
public virtual bool Any(Expression<Func<T, bool>> expression)
{
return _dbSet.Any(expression);
}
public virtual void Delete(T entity)
{
_dbSet.Remove(entity);
_db.Commit();
}
public virtual IEnumerable<T> All()
{
return _dbSet.ToList();
}
public virtual T Update(T entity, bool attachOnly = false)
{
_dbSet.Attach(entity);
_db.SetModified(entity);
if (!attachOnly) _db.Commit();
return entity;
}
#endregion
protected User GetCurrentUser()
{
return
_db.Set<User>().Find(HttpContext.Current != null ? ((User) HttpContext.Current.Session["User"]).Id : 1);
}
BaseTrackableEntityRepository -
public class BaseTrackableEntityRepository<T> : BaseRepository<T>, IBaseTrackableEntityRepository<T>
where T : TrackableEntity
{
private readonly IAppDb _db;
private readonly IDbSet<T> _teDB;
public BaseTrackableEntityRepository(IAppDb db)
: base(db)
{
_db = db;
_teDB = _db.Set<T>();
}
#region IBaseTrackableEntityRepository<T> Members
public virtual T SetDeleteFlag(int id)
{
var entity = _teDB.Find(id);
if (entity == null) return null; //throw exception
entity.IsDeleted = true;
entity.DateModified = DateTime.Now;
entity.ModifiedBy = GetCurrentUser();
return Update(entity);
}
public override IEnumerable<T> All()
{
return _teDB.Where(e => !e.IsDeleted).ToList();
}
public override T Add(T entity)
{
var curUser = GetCurrentUser();
entity.CreatedBy = curUser;
entity.ModifiedBy = curUser;
entity.DateCreated = DateTime.Now;
entity.DateModified = DateTime.Now;
entity.Active = true;
entity.IsDeleted = false;
_teDB.Add(entity);
_db.Commit();
return entity;
}
public override T Update(T entity, bool attachOnly = false)
{
InsertTeData(ref entity);
entity.ModifiedBy = GetCurrentUser();
entity.DateModified = DateTime.Now;
_teDB.Attach(entity);
_db.SetModified(entity);
if (!attachOnly) _db.Commit();
return entity;
}
public virtual T SetStatus(int id, bool status)
{
var entity = _teDB.Find(id);
if (entity == null) return null;
entity.Active = status;
return Update(entity);
}
#endregion
private void InsertTeData(ref T entity)
{
if (entity == null || entity == null) return;
var dbEntity = GetById(entity.Id);
if (dbEntity == null) return;
_db.Detach(dbEntity);
entity.CreatedBy = dbEntity.CreatedBy;
entity.DateCreated = dbEntity.DateCreated;
entity.ModifiedBy = dbEntity.ModifiedBy;
entity.DateModified = dbEntity.DateModified;
}