System.NullReferenceException using list of T in app.xaml.cs - windows-phone-8

I'm trying to store objects in a List of T to use the list with all my pages in my Windows Phone 8 app.
This is my List in App.xaml.cs:
public partial class App : Application
{
public List<Worker> listWorkers { get; set; }
/// <summary>
/// Provides easy access to the root frame of the Phone Application.
/// </summary>
/// <returns>The root frame of the Phone Application.</returns>
public static PhoneApplicationFrame RootFrame { get; private set; }
This is my code behind:
private void buttonGo_Click(object sender, RoutedEventArgs e)
{
(App.Current as App).listWorkers.Add(new Worker { Name = "Test", Age = 15 });
textBlockOutput.Text = (App.Current as App).listWorkers.Count.ToString();
}
And this is my Worker class:
public class Worker
{
public string Name { get; set; }
public int Age { get; set; }
}
The exception is:
System.NullReferenceException was unhandled by user code
Thanks in advance!

That's totally normal. Where are you initializing the listWorkers property? before you can use .Add method you need to create a new instance of the list, for example in the App.xaml.cs constructor:
listWorkers = new List< Worker>();

From your code, it seems you have forgotten to initialize the list before using it:
listWorkers = new List<Worker>();
By the way, this kind of exception is very easy to see the cause in debugging mode.

Related

MySql Entity Framework error when using SaveChangesAsync ASP.NET Core

I'm gettting an error when I try to use SaveChangesAsync with MySql EntityFramewok in a ASP.NET Core environment in dev mode in VS Code. Everything else works fine. No problems when using SaveChanges() either, without the async. Wonder if anyone else has this issue.
The error looks like this:
InvalidOperationException: Connection must be valid and open to commit transaction
MySql.Data.MySqlClient.MySqlTransaction.Commit()
The piece of code in the controller looks like this:
[HttpPut("/api/strategy/{id}")]
public async Task<IActionResult> UpdateStrategy(int id, [FromBody] StrategyResource newStrategy)
{
if(!ModelState.IsValid)
return BadRequest(ModelState);
mapper.Map<StrategyResource, Strategy>(newStrategy, strategyInDb );
context.SaveChanges(); // works fine
//await context.SaveChangesAsync(); gives ERROR
var res = mapper.Map<Strategy, StrategyResource>(strategyInDb );
return Ok(res);
}
Context initialization in the constructor of the controller (nothing special really)
private readonly JTradeContext context;
private readonly IMapper mapper;
public TradesController(JTradeContext context, IMapper mapper)
{
this.mapper = mapper;
this.context = context;
}
Context is initially added to services int the start up class
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<JTradeContext>();
}
And finally the context class itself
public class JTradeContext:DbContext
{
public DbSet<Trade> Trades { get; set; }
public DbSet<WebClient> WebClients { get; set; }
public DbSet<Strategy> Strategies { get; set; }
public DbSet<Portfolio> Portfolios { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySQL("my connection string here");
}
}

mvvmcross Init method is not called if I inherit froma base ViewModel which is derived from MvxViewModel

First I'm using mvvmcross version 3.0.13. When a class is inherited from a base class, which is inherited from MvxViewModel, the Init method won't be called from IoC. Current ugly workaround is to call the Init in the constructor. Could this be a bug or is there another pattern to use?
In both classes (base and child of that base) it won't be called. For example:
public class BaseViewModel : MvxViewModel
{
protected CDataImportService DataImportService { get; private set; }
protected CSettingService SettingService { get; private set; }
protected CDataService DataService { get; private set; }
protected CDocumentService DocumentService { get; private set; }
public BaseViewModel(IDataService objDataService, IDataImportService objDataImportService, IDocumentService objDocumentService, ISettingService objSettingService)
{
DataImportService = (CDataImportService)objDataImportService;
SettingService = (CSettingService)objSettingService;
DataService = (CDataService)objDataService;
DocumentService = (CDocumentService) objDocumentService;
}
public void Init()
{
Mvx.Trace("Init called in {0}", GetType().Name);
}
}
public class DocumentsViewModel : BaseViewModel
{
public MenuViewModel(IDataService objDataService, IDataImportService objDataImportService, IDocumentService objDocumentService, ISettingService objSettingService)
: base(objDataService, objDataImportService, objDocumentService, objSettingService)
{
}
}
IOC on it's own does not call the Constructor-Init-Reload-Start sequence.
IOC is a general C# service, and only calls the constructor part.
If you want the entire sequence called then you can access this via the IMvxViewModelLoader object - e.g Mvx.Resolve<IMvxViewModelLoader>().LoadViewModel(MvxViewModelRequest<MyViewModel>.GetDefaultRequest(), null);
By default, this will use the Default ViewModel Locator to create a view model instance - https://github.com/MvvmCross/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross/ViewModels/MvxDefaultViewModelLocator.cs
If it helps, for some more information:
mvvmcross IOC is described fully in https://github.com/MvvmCross/MvvmCross/wiki/Service-Location-and-Inversion-of-Control
view model location is briefly discussed in https://github.com/MvvmCross/MvvmCross/wiki/Customising-using-App-and-Setup

DbSet.Attach, what exactly does it do?

Follow the methods below:
public class User
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
public class DataContext : DbContext
{
DbSet<User> Users { get; set; }
}
public class Repository
{
DataContext db = new DataContext();
public User Attach1(User entity)
{
var ent = db.Entry<User>(entity);
ent.State = EntityState.Modified;
if (db.SaveChanges() > 0)
return ent.Entity;
return null;
}
public User Attach2(User entity)
{
return db.Users.Attach(entity);
}
}
Is there any difference between Attach1 and Attach2?
Your Attach1 and Attach2 methods perform different things and it is not clear what you expect to do in these methods. When you attach an entity to EF it will be added to the context in Unchanged state. If you modify the entity after attaching, then EF will track those changes and the entity will be in Modified state.
Attach1
This method will attach an entity and mark it as modified. So the subsequent SaveChanges() will update all the properties of the entity. Calling SaveChanges() inside the Attach method is not recommended since it does more than attaching.
Attach2
This method will attach the entity as Unchanged.

EF Code First, create new object in collection with a proxy

How can I create+persist+have-a-proxy-to a new instance of a code-first poco using only navigation property collections? In the bellow code, I show how you might want to do this, if using member functions to create POCOs that then create POCOs. You don't have a DbContext, but if you create an object and persist it using DbSet.Add, the returned object isn't a proxy, so you can't in turn use its DbSet.Add to add a different sub-object.
In this code, if you call MailingList.AddIncomingMessage("my message"), you get an exception at the "OOPS" comment, because the created msg isn't a proxy and thus its Message.doodads property is null.
class Doodad {
public int ID { get; set; }
public string doodad { get; set; };
}
class Message {
public int ID { get; set; }
public virtual MailingList mailingList { get; set; }
public virtual ICollection<Doodad> doodads { get; set; }
public string text { get; set; }
public void GetDoodadCreateIfNeeded(string doodad) {
try {
// won't be found since we just created this Message
return this.doodads.First(d => d.doodad == doodad);
} catch (Exception e) {
Doodad newDoodad = new Doodad() { doodad=doodad };
// OOPS! this.doodads == null, because its not a proxy object
this.doodads.Add(newDoodad);
return newDoodad;
}
}
}
class MailingList {
public int ID { get; set; }
public virtual ICollection<Message> messages { get; set; }
public void AddIncomingMessage(string message) {
var msg = new Message() { text=message };
// we have no Context, because we're in a POCO's member function
this.messages.Add(msg);
var doodad = msg.GetDoodadCreateIfNeeded("bongo drums");
}
}
EDIT: sorry guys, I forgot to put the property accessors and ID in for this simplified case, but I am using them in the actual code.
It has nothing to do with proxies. It is the same as any other code - if you want to use object / collection you must first initialize it! Your fist command:
return this.doodads.First(d => d.doodad == doodad);
doesn't throw exception because it didn't find doodad but because the doodads is null.
What do you need to do? You need to initialize collections before you first use them. You can do it:
Directly in their definition
In entity's constructor
In property getter (lazy initialization) once they are first needed - that would require to change your fields to properties which is btw. correct way to write classes in .NET
In your custom methods you can check if they are null and initialize them
Complementary to the navigation property, you need to have a property that is the Id of the foreign key.
So your MailingList will need to have this property:
[Key] // this attribute is important
public int Id { get; set; }
and you'll have to change the Message classe to have these properties:
public virtual int mailingListId { get; set;
public virtual MailingList mailingList { get; set; }
The { get; set; } property is important, so that it is a property, not just a public attribute.

Customizing Linq to Sql DataContext

Is there anyway simple ways to add a property to Linq to Sql generated entity to reference its DataContext?
For example:
var myContext = new DataContext();
var product = context.Products.Where(p => p.Id == productId).SingleOrDefault();
and product entity has a property called "Context" (product.Context) that has a reference to the myContext, datacontext.
I know how to customize generated entities. My question is how to customize (i think DataContext) to set 'Context' property of each instance that it creates to itself.
I'm not sure I'm doing the right thing or not. I want to write a business encapsulation model that has best performance with less code.
As i googled around I have find out that the DataContext object is very lightweight and there for I thought it would be a good way to add an instance of DataContext to each object. This will reduce the need to attach, detached objects again to a new instance of datacontext every time I want to update or delete them.
If you have any other solution I will really appreciate it.
Thanks
Is there a simple way to add a property to Linq to Sql generated entity to reference its DataContext?
There is no simple way to achieve this.
In doing this, you defeat part of the purpose of LINQ-to-SQL. One of the purposes is to allow to you work with the objects that you have, and not have to change your design based on database considerations.
In attaching the DataContext to the database, you are coupling your representation in code with the means to persist it, which is generally a bad design idea.
If you feel you must do this though, you can always derive from the class and then implement an interface on that class which exposes the DataContext.
I recommend implementing the interface, since you can't indicate a base class to the LINQ-to-SQL designer, and you want to be able for all of your entities to have a shared implementation.
See here: Determine the source DataContext for a Linq to Sql query
I asked more or less the same question. You can get the context from the IQueryable that a linq to sql query returns, but not from the entity itself as far as I know.
Actually, I agree to casperOne. If you really have to need this, I remembered that the classes that linq-to-sql generates are partial. So you can write a partial class to any class you want and add extended functionalities to it.
Pass the data context as a ref parameter to a custom method on your partial Product object:
public partial class Product
{
public string GetSomethingElse(ref DataContext dbase)
{
return dbase.OtherTableWhatever.Count.ToString(); // whatever
}
}
Inside your aspx.cs:
var context = new DataContext();
var product = context.Products.SingleOrDefault(x => x.id == 1);
var s = product.GetSomethingElse(ref context);
Here is a custom wrapper I made for System.Data.Linq. It contains a find method, so instead of your code:
var myContext = new DataContext();
var product = context.Products.Where(p => p.Id == productId).SingleOrDefault();
you can do this
var myContext = new DataContext();
var product = context.Products.Find(productId); //(assuming productId is your primary key)
You can grab the code below and do any custom modifications you wish to set product.Context, but this is an example of modifying the DataContext.
I also made save and delete methods. You'll notice I go out a regrab the record even though it is being passed in. I do this because the record might get detached from the context and not update. If anyone would like the full code I can post the github link.
public abstract class DbContext : IDisposable
{
#region Properties
private string _connectionString { get; set; }
private DataContext _context { get; set; }
#endregion
#region Constructor
public DbContext(string connectionString)
{
_connectionString = connectionString;
_context = new DataContext(_connectionString);
Initialized(_context);
}
public DbContext(string server, string database, string userID, string password)
{
_connectionString = string.Format(
"Server={0};Database={1};User Id={2};Password={3};MultipleActiveResultSets=true",
server,
database,
userID,
password);
_context = new DataContext(_connectionString);
Initialized(_context);
}
#endregion
#region Methods
/// <summary>
/// Is used to get the contents of a Sql Server Table.
/// </summary>
/// <typeparam name="TEntity">Type</typeparam>
/// <returns>Table</returns>
public Table<TEntity> GetTable<TEntity, TPKType>()
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
return _context.GetTable<TEntity>();
}
/// <summary>
/// Is used to get the contents of a Sql Server Table.
/// </summary>
/// <typeparam name="TEntity">Type</typeparam>
/// <returns>Table</returns>
public Table<TEntity> GetTable<TEntity>()
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
return GetTable<TEntity, long>();
}
protected virtual void Initialized(DataContext context) { }
/// <summary>
/// Saves the changes to the database. In order to save the table must inherit from DbTableEquatable
/// and be a type of IDbTableEquatable and the Primary Key Type must be a C# Structure
/// </summary>
/// <typeparam name="TEntity">Record Type</typeparam>
/// <typeparam name="TPKType">Primary Key Type</typeparam>
/// <param name="entity">Record</param>
public virtual void SaveChanges<TEntity, TPKType>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
var changedList = _context.GetTable<TEntity>();
var ID = entity.GetType().GetProperty("ID").GetValue(entity);
_preprocessSave<TEntity, TPKType>(entity);
// Save changes
if (Convert.ToInt64(ID) == 0)
{
// Insert
// If No ID we need to insert on submit
_context.GetTable<TEntity>().InsertOnSubmit((TEntity)entity);
_context.SubmitChanges();
}
else
{
// Update
var item = changedList.Where(w => w.Equals(entity)).FirstOrDefault();
ReflectionManager.SetValuesWithSkip(entity, item, "ID");
_context.SubmitChanges();
}
Refresh();
}
/// <summary>
/// Saves the changes to the database. In order to save the Table the Record is from must inherit from DbTableEquatable
/// and be a type of IDbTableEquatable and the Primary Key Type must be a C# Structure
/// </summary>
/// <typeparam name="TEntity">Record Type</typeparam>
/// <param name="entity">Record</param>
public virtual void SaveChanges<TEntity>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
SaveChanges<TEntity, long>(entity);
}
/// <summary>
/// Saves any non committed changes to the database
/// </summary>
public void SaveChanges()
{
_context.SubmitChanges();
Refresh();
}
/// <summary>
/// Marks the record as delete and will be deleted when saved
/// </summary>
/// <typeparam name="TEntity">Record Type</typeparam>
/// <typeparam name="TPKType">Primary Key Type</typeparam>
/// <param name="entity">Record</param>
public virtual void DeleteOnSave<TEntity, TPKType>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
var item = _context.GetTable<TEntity>().Where(w => w.Equals(entity)).FirstOrDefault();
_context.GetTable<TEntity>().DeleteOnSubmit((TEntity)item);
}
/// <summary>
/// Marks the record as delete and will be deleted when saved
/// </summary>
/// <typeparam name="TEntity">Record Type</typeparam>
/// <param name="entity">Record</param>
public virtual void DeleteOnSave<TEntity>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
DeleteOnSave<TEntity, long>(entity);
}
protected virtual void _preprocessSave<TEntity, TPKType>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
}
protected virtual void _preprocessSave<TEntity>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
_preprocessSave<TEntity, long>(entity);
}
public void Dispose()
{
_connectionString = "";
_context.Dispose();
_context = null;
}
public virtual void Refresh<TEntity>(RefreshMode mode, TEntity entity) where TEntity : class
{
_context.Refresh(RefreshMode.OverwriteCurrentValues, entity);
}
public virtual void Refresh()
{
_context = new DataContext(_connectionString);
}
public virtual void Refresh<TEntity>(RefreshMode mode, params TEntity[] entities) where TEntity : class
{
_context.Refresh(RefreshMode.OverwriteCurrentValues, entities);
}
public virtual void Refresh<TEntity>(RefreshMode mode, IEnumerable<TEntity> entities) where TEntity : class
{
_context.Refresh(RefreshMode.OverwriteCurrentValues, entities);
}
#endregion
}
Extenstions
public static class Extension
{
public static TEntity Find<TEntity, TPKType>(this Table<TEntity> table, TPKType ID, string pkName = "ID")
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
TEntity copy = Activator.CreateInstance<TEntity>();
// set value through reflection
copy.GetType().GetProperty(pkName).SetValue(copy, ID, null);
return (TEntity)table.Where(w => w.Equals(copy)).FirstOrDefault();
}
public static TEntity Find<TEntity>(this Table<TEntity> table, long ID, string pkName = "ID")
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
TEntity copy = Activator.CreateInstance<TEntity>();
// set value through reflection
copy.GetType().GetProperty(pkName).SetValue(copy, ID, null);
return (TEntity)table.Where(w => w.Equals(copy)).FirstOrDefault();
}
}
}
Interface/Abstraction
/// <summary>
/// This Class Assumes the type T has a property called ID. MUST be
/// used with IDbEquatable
/// </summary>
/// <typeparam name="T">Class Type</typeparam>
public abstract class DbTableEquatable<T> : IEquatable<T> where T : class
{
public bool Equals(T other)
{
//Check whether the compared object is null.
if (Object.ReferenceEquals(other, null))
{
return false;
}
//Check whether the compared object references the same data.
if (Object.ReferenceEquals(this, other))
{
return true;
}
return ((dynamic)other).ID == ((dynamic)this).ID;
}
}
/// <summary>
/// Needs to be inherited from in order for Ion.Data.Linq functions to work
/// </summary>
/// <typeparam name="T">Primary Key Type</typeparam>
public interface IDbTableEquatable<T>
{
T ID { get; set; }
}
here is a table implementation
[Table(Name = "Crews")]
public class Crew : DbTableEquatable<IDbTableEquatable<long>>, IDbTableEquatable<long>
{
[Column(IsPrimaryKey = true, DbType = "Bigint NOT NULL IDENTITY", AutoSync = AutoSync.OnInsert, IsDbGenerated = true)]
public long ID { get; set; }
[Column]
public string Alias { get; set; }
[Column]
public string DefaultForeground { get; set; }
[Column]
public string DefaultBackground { get; set; }
[Column]
public string AccountEmailAddress { get; set; }
[Column]
public long? CrewLeaderEmployeeID { get; set; }
[Column]
public string Comments { get; set; }
[Column]
public string Password { get; set; }
[Column]
public string PrivateICSLink { get; set; }
[Column]
public string PrivateXMLLink { get; set; }
}