Troubleshoot object reference error when filling mvc models with datareader? - asp.net-mvc-3

I am using MVC 3 and I am using a datareader to create a list of items that have subItems. When I add the subitem I get "Object reference not set to an instance of an object." With the following code:
QuestionaireLine question = new QuestionaireLine();
question.Question_ID = Convert.ToInt32(reader["Question_ID"]);
question.Question_Answer = reader["Question_Answer"].ToString();
...etc..
currentGroup.Lines.Add(question); //exception thrown here
The models:
public class Questionaire
{
public int Question_Group_Id { get; set; }
public string Question_Group_Name { get; set; }
public int Question_Group_Indent { get; set; }
public int Question_Group_Order { get; set; }
public List<QuestionaireLine> Lines { get; set; }
}
public class QuestionaireLine
{
public int Question_ID { get; set; }
public string Question_Label { get; set; }
public string Question_Answer { get; set; }
public int Data_Type { get; set; }
public int Control_Type { get; set; }
public string Data_Choices { get; set; }
public int Data_Max_Length { get; set; }
public bool Issue_Tagged { get; set; }
public int Question_Order { get; set; }
public string NumberedQuestion
{
get { return String.Format("{0}. {1}", Question_Order, Question_Label); }
}
}
The whole code:
// what am I missing??
using (var conn = new SqlConnection(_connectionString))
{
List<Questionaire> groups = new List<Questionaire>();
var com = new SqlCommand();
com.Connection = conn;
com.CommandType = CommandType.StoredProcedure;
com.Parameters.Add(new SqlParameter
{
ParameterName = "#Review_ID",
Value = reviewID
});
com.CommandText = "Review_Get_Question_Groups_Answers";
conn.Open();
// Get the reader
SqlDataReader reader = com.ExecuteReader();
// Process each result in the result set
int currQuestionGroupId = 0;
Questionaire currentGroup = null;
while (reader.Read())
{
var questionGroupId = Convert.ToInt32(reader["Question_Group_Id"]);
if (questionGroupId != currQuestionGroupId)
{
currQuestionGroupId = questionGroupId;
if (currentGroup != null)
{
groups.Add(currentGroup);
}
currentGroup = new Questionaire();
currentGroup.Question_Group_Id = Convert.ToInt32(reader["Question_Group_Id"]);
currentGroup.Question_Group_Indent = Convert.ToInt32(reader["Question_Group_Indent"]);
currentGroup.Question_Group_Name = reader["Question_Group_Name"].ToString();
currentGroup.Question_Group_Order = Convert.ToInt32(reader["Question_Group_Order"]);
}
if (reader["Question_ID"] != DBNull.Value)
{
QuestionaireLine question = new QuestionaireLine();
question.Question_ID = Convert.ToInt32(reader["Question_ID"]);
question.Question_Answer = reader["Question_Answer"].ToString();
question.Issue_Tagged = Convert.ToBoolean(reader["Issue_Tagged"]);
question.Data_Type = Convert.ToInt32(reader["Data_Type"]);
question.Data_Max_Length = Convert.ToInt32(reader["Data_Max_Length"]);
question.Data_Choices = reader["Data_Choices"].ToString();
question.Question_Label = reader["Question_Label"].ToString();
question.Question_Order = Convert.ToInt32(reader["Question_Order"]);
question.Control_Type = Convert.ToInt32(reader["Control_Type"]);
currentGroup.Lines.Add(question);
}
if (currentGroup != null)
{
groups.Add(currentGroup);
}
}
reader.Close();
com.Dispose();
return groups;
}

Your Lines property on your Questionaire instance is Null. Change to:
public class Questionaire
{
public int Question_Group_Id { get; set; }
public string Question_Group_Name { get; set; }
public int Question_Group_Indent { get; set; }
public int Question_Group_Order { get; set; }
public List<QuestionaireLine> Lines { get; set; }
public Questionaire() {
Lines = new List<QuestionaireLine>();
}
b.t.w. stepping through your code would have shown you that.

Related

Linq ORM map Object to 3 level Object

I have object like this. This include Group Question (QG), 1 group question has many Question(Q), 1 question has many answer.
public class CrmQuestionAnswer
{
public long QgId { get; set; }
public string QgName { get; set; }
public int QgMIndex { get; set; }
public int QgMdf { get; set; }
public string QgDescription { get; set; }
public long QId { get; set; }
public long QParentId { get; set; }
public string QName { get; set; }
public string QDescription { get; set; }
public int QMindex { get; set; }
public int QMdf { get; set; }
public bool IsMainQuestion { get; set; }
public bool IsTitle { get; set; }
public int QTypeId { get; set; }
public long AnswerId { get; set; }
public string AnswerName { get; set; }
public string AnswerValue { get; set; }
public int AnswerMdf { get; set; }
public int AnswerMIndex { get; set; }
public string AnswerDescription { get; set; }
public long? LinkQuestionId { get; set; }
}
I want to use Linq to map List CrmQuestionAnswer to List QuestionGroupView
public class QuestionGroupView:Title
{
public List<CrmQuestionView> Questions;
}
public class CrmQuestionView: Title
{
public long? ParentId;
public bool? IsMainQuestion;
public bool? IsTitle;
public long? LinkQuestionId;
public List<CrmAnswerView> Answers;
}
public class CrmAnswerView : Title
{
public long? LinkQuestionId;
}
Title is base class:
public class Title
{
public long Id { get; set; }
public string Name { get; set; }
public int MIndex { get; set; }
public int Mdf { get; set; }
public int Type { get; set; }
public string Description { get; set; }
}
I use this code:
public List<QuestionGroupView> GetListQuestionsAnswers(long themaId)
{
var questionAnswerDao = new CrmQuestionAnswerDao();
var questionAnswerlist = questionAnswerDao.GetByThemasId(themaId);
//map List CrmQuestionAnswer -> List QuestionGroupView: 3 level
var listquestiongroup = questionAnswerlist
.OrderBy(t => t.QgMIndex)
.ThenBy(t => t.QMindex)
.GroupBy(t => t.QgId)
.Select(GetQuestionGroup)
.ToList();
return listquestiongroup;
}
private static QuestionGroupView GetQuestionGroup(IGrouping<long, CrmQuestionAnswer> grouping)
{
var group = grouping.First();
var question = new QuestionGroupView
{
Id = group.QgId,
Name = group.QgName,
Description = group.QgDescription,
Mdf = group.QgMdf,
MIndex = group.QgMIndex,
Questions = grouping
.Select(p => new CrmQuestionView
{
Id = p.QId,
Name = p.QName,
Description = p.QDescription,
Mdf = p.QMdf,
MIndex = p.QMindex,
Type = p.QTypeId,
ParentId = p.QParentId,
IsMainQuestion = p.IsMainQuestion,
IsTitle = p.IsTitle,
Answers = grouping//**This line is wrong**
.GroupBy(g => g.QId)
.Select(GetTitle)
.ToList()
})
.ToList()
};
return question;
}
private static CrmAnswerView GetTitle(IGrouping<long, CrmQuestionAnswer> grouping)
{
var group = grouping.First();
var answer = new CrmAnswerView
{
Id = group.AnswerId,
Name = group.AnswerName,
Description = group.AnswerDescription,
MIndex = group.AnswerMIndex,
Mdf = group.AnswerMdf,
Type = group.QTypeId,
LinkQuestionId = group.LinkQuestionId,
};
return answer;
}
This is data get from server Data
My code gets right Group question (2 group) with right List question, but it gets wrong list answer from data.
Can some help me ?
Best regards

insert data in two class(table) in Entity Framwork by rerlation many to many

i create two class in my model and create relation many to many by Entity
in sql my classes is created tables Properly
when i try to insert data in this table get show error "Object reference not set to an instance of an object." my cod is:
public class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
public virtual Picture Picture { get; set; }
public virtual NewsType NewsType { get; set; }
public ICollection<Tag> Tag { get; set; }
public News(int id, string title, string content, DateTime date)
{
this.ID = id;
this.Title = title;
this.Content = content;
this.Date = date;
}
public News()
{
}
}
public class Tag
{
public int ID { get; set; }
public string Title { get; set; }
public ICollection<News> News { get; set; }
public Tag()
{
}
}
public class DatabaseContext : DbContext
{
public DatabaseContext()
: base("News")
{
}
static DatabaseContext()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<DatabaseContext>());
}
public DbSet<News> newsInfo { get; set; }
public DbSet<Picture> pictures { get; set; }
public DbSet<NewsType> Types { get; set; }
public DbSet<Tag> Tags { get; set; }
}
[HttpPost]
public ActionResult AddNews(NewsViewModel newsInfo)
{
using (Models.DatabaseContext dbContext = new DatabaseContext())
{
ViewData["Type"] = new SelectList(dbContext.Types.ToList(), "Id", "Title");
}
if (!ModelState.IsValid)
{
return View();
}
else
{
Models.DatabaseContext dbContext = new Models.DatabaseContext();
Models.News news = new Models.News();
news.Title = newsInfo.Title;
news.Content = newsInfo.Content;
news.Date = DateTime.Now;
string newsinput = newsInfo.Tag.cleanTag();
string[] tags = new string[] { };
if (newsinput != null)
{
tags = newsinput.Split(',');
}
foreach (string item in tags)
{
Tag findTag = dbContext.Tags.Where(x => x.Title == item).FirstOrDefault();
if (findTag != null)
{
news.Tag.Add(findTag)
////////////////////////show error in this line
}
}
news.NewsType = dbContext.Types.Find(Convert.ToInt32(Request.Form["rdb"]));
dbContext.newsInfo.Add(news);
dbContext.SaveChanges();
return View();
}

Select Foreign key data in EF

I have 2 models : Account and Task
public class Account
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Key]
public Guid UserId { get; set; }
public string UserType { get; set; }
public string Name { get; set; }
}
public class Task
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[Key]
public Guid TaskId { get; set; }
[ForeignKey("TaskSubType")]
public Guid TaskSubTypeId { get; set; }
public virtual TaskSubType TaskSubType { get; set; }
[ForeignKey("Account")]
public Guid TaskCreator { get; set; }
public virtual Account Account { get; set; }
}
I call getTasks:
public List<TaskOverViewViewModel> GetTasks()
{
IEnumerable<Task> result = db.Tasks.AsEnumerable();
List<TaskOverViewViewModel> list = ToViewModelMapper.toViewModel(result);
return list;
}
public class ToViewModelMapper
{
internal static List<TaskOverViewViewModel> toViewModel(IEnumerable<Task> entitys )
{
List<TaskOverViewViewModel> modelList = new List<TaskOverViewViewModel>();
foreach (var entity in entitys)
{
TaskOverViewViewModel model = new TaskOverViewViewModel();
model.SubTaskName = entity.TaskSubType.Name;
model.TaskCreator = entity.Account.LoginName;
model.ToolsAccesable = entity.ToolsAccesable;
modelList.Add(model);
}
return modelList;
}
}
But it fails because i entity.TaskSubType and entity.Account is null. But if i return IEnumerable<Task> result = db.Tasks.AsEnumerable(); in the call everything works fine and i can see that Json contains all TaskSubtype and Account models.
From linq-to-entities, you can project directly to your ViewModel class.
public List<TaskOverViewViewModel> GetTasks()
{
List<TaskOverViewViewModel> result = (from t in db.Tasks
select new TaskOverViewViewModel
{
SubTaskName = t.TaskSubType.Name;
TaskCreator = t.Account.LoginName;
ToolsAccesable = t.ToolsAccesable;
}).ToList();
return result;
}
If you prefer method syntax, you can use this:
List<TaskOverViewViewModel> result = db.Tasks.Select(t => new TaskOverViewViewModel
{
SubTaskName = t.TaskSubType.Name;
TaskCreator = t.Account.LoginName;
ToolsAccesable = t.ToolsAccesable;
}).ToList();

Resolving LINQ Error: Missing Query Pattern Implementation

I am receiving a strange LINQ error when trying to filter a collection in my view.
This is my model:
public class adminEditProductsPricelistProductsVM
{
public Product Product { get; set; }
public PricelistProduct pricelistProduct { get; set; }
}
This is my view:
#using Pp.Lib.Models;
#using System.Linq;
#model PpLib.viewModels.admin.adminEditProductsPricelistProductsVM
#{
//get corresponding PricelistProduct
PricelistProduct thisPP = new ProofPixLib.Models.PricelistProduct();
thisPP = (from x in Model.pricelistProduct where x.ProductId == Model.Product.ProductId select x).FirstOrDefault();
}
the Model.pricelistProduct line is underlined in VS and it says the following error:
Could not find an implementation of the query pattern for source type Pp.Lib.Models.PricelistProduct. 'Where' not found.
Thanks in advance for your help!
UPDATE
As requested - here is the code for the PricelistProduct model.
public partial class PricelistProduct
{
public PricelistProduct()
{
this.PricelistProductOptions = new List<PricelistProductOption>();
}
[ReadOnly(true)]
[Display(Name = "Pricelist Product ID")]
public int PricelistProductId { get; set; }
[ReadOnly(true)]
[Display(Name = "Pricelist ID")]
public int PricelistId { get; set; } //foregin key
public virtual Pricelist Pricelist { get; set; }
[ReadOnly(true)]
[Display(Name = "Product ID")]
public int ProductId { get; set; } //foreign key
public virtual Product Product { get; set; }
[HiddenInput]
public int ProductCategoryId { get; set; } // not a FK but data only
public virtual ProductCategory ProductCategory { get; set; }
[Display(Name = "Use formula")]
private bool _UsesFormula = true;
public bool UsesFormula { get { return _UsesFormula; } set { _UsesFormula = value; } }
private decimal _Price = 0;
public decimal Price { get { return _Price; } set { _Price = value; } }
[Display(Name = "Use discount pricing")]
private bool _HasDiscountPricing = false;
public bool HasDiscountPricing { get { return _HasDiscountPricing; } set { _HasDiscountPricing = value; } }
[Display(Name = "Local shipping price")]
private decimal _LocalShipPrice = 0;
public decimal LocalShipPrice { get { return _LocalShipPrice; } set { _LocalShipPrice = value; } }
[Display(Name = "Intl. shipping price")]
private decimal _IntlShipPrice = 0;
public decimal IntlShipPrice { get { return _IntlShipPrice; } set { _IntlShipPrice = value; } }
[Display(Name = "Item is taxable")]
private bool _isTaxable = true;
public bool isTaxable { get { return _isTaxable; } set { _isTaxable = value; } }
public virtual List<PricelistProductOption> PricelistProductOptions { get; set; }
}
Your PricelistProduct class doesn't implement IEnumerable or IQuerable interfaces, other words it's not a collection to query over it.
Maybe it should be Model.pricelistProduct.PricelistProductOptions in your query or your view model should be a collection?
Consecutive assignments don't make sense as well:
#{
//get corresponding PricelistProduct
PricelistProduct thisPP = new ProofPixLib.Models.PricelistProduct();
thisPP = ..;
}

Refactor to filtering lists using LINQ

I use several lists of similar objects. Anyone object has a List property. Basically, I need compare several lists.
I would have thought that LINQ would be an ideal way of doing this but after trying joins, extension methods, using yields, etc. I'm still having trouble.
any suggestions for refactor my code to using LINQ ?
Update: I'm refactor ContieneServidor (ContainsServer translate) method
private static bool ContieneServidorRefactoring(List<GrupoServidorDto> datosGruposServidores, string nombreMaquina)
{
var total = datosGruposServidores
.SelectMany(g => g.Servidores)
.Where(x => x.Nombre.Equals(nombreMaquina)).Count();
if (total > 0) return true;
return false;
}
My code:
var datosGruposServidores = new List<GrupoServidorDto>();
var gruposCompletos = new List<GrupoServidorSeleccionado>();
var maquinasSeleccionadas = new List<string>();
...
// Comprobación de Máquinas
var maquinasNoEncontradas = new List<string>();
foreach (var g in gruposCompletos)
{
foreach (var server in g.Servidores)
{
var encontrado =
ContieneServidor(datosGruposServidores, server.Nombre);
if (!encontrado) maquinasNoEncontradas.Add(server.Nombre);
}
}
foreach (var m in maquinasSeleccionadas)
{
var encontrado = ContieneServidor(datosGruposServidores, m);
if (!encontrado) maquinasNoEncontradas.Add(m);
}
if (maquinasNoEncontradas.Count > 0)
{
var sb = new StringBuilder();
var sep = "";
foreach (var maq in maquinasNoEncontradas)
{
sb.Append(sep + maq);
sep = ", ";
}
System.Diagnostics.Trace.WriteLine("Máquinas no encontradas: " + sb.ToString());
throw new InvalidOperationException("Máquinas no encontradas: " + sb.ToString());
}
}
private static bool ContieneServidor(
List<GrupoServidorDto> datosGruposServidores, string nombreMaquina)
{
foreach (var g in datosGruposServidores)
{
var servidor = g.Servidores.Where(s => s.Nombre.Equals(nombreMaquina));
if (servidor != null && servidor.Count() > 0) return true;
}
return false;
}
private static bool ContieneServidorRefactoring(List<GrupoServidorDto> datosGruposServidores, string nombreMaquina)
{
var total = datosGruposServidores
.SelectMany(g => g.Servidores)
.Where(x => x.Nombre.Equals(nombreMaquina)).Count();
if (total > 0) return true;
return false;
}
The types:
public class GrupoServidorDto
{
public int IdGrupo { get; set; }
public string Nombre { get; set; }
private List<ServidorDto> servidores = new List<ServidorDto>();
public List<ServidorDto> Servidores
{
get { return servidores; }
set { servidores = value; }
}
}
public class ServidorDto
{
public int Id { get; set; }
public string Nombre { get; set; }
public string IP { get; set; }
public string Entorno { get; set; }
public string Habilitado { get; set; }
public string Tipo { get; set; }
public int IdGrupo { get; set; }
}
[Serializable()]
public class GrupoServidorSeleccionado
{
[XmlAttribute()]
public int IdGrupo { get; set; }
[XmlAttribute()]
public string Nombre { get; set; }
private List<ServidorSeleccionado> servidores =
new List<ServidorSeleccionado>();
[XmlElement()]
public List<ServidorSeleccionado> Servidores
{
get { return servidores; }
set { servidores = value; }
}
[XmlAttribute()]
public bool EstanTodasLasMaquinasSeleccionadas { get; set; }
public GrupoServidorSeleccionado() { }
}
[Serializable()]
public class ServidorSeleccionado
{
[XmlAttribute()]
public int Id { get; set; }
[XmlAttribute()]
public string Nombre { get; set; }
[XmlAttribute()]
public string IP { get; set; }
[XmlAttribute()]
public string Entorno { get; set; }
[XmlAttribute()] // [XmlIgnore()]
public string Habilitado { get; set; }
[XmlAttribute()]
public string Tipo { get; set; }
[XmlAttribute()]
public int IdGrupo { get; set; }
}
I think you want:
var maquinasNoEncontradas = gruposCompletos
.SelectMany(g => g.Servidores)
.Select(x => x.Nombre)
.Concat(maquinasSeleccionadas)
.Where(x => !ContieneServidor(datosGruposServidores, x))
.ToList();
And then:
if (maquinasNoEncontradas.Count > 0)
{
// This assumes .NET 4; it's *slightly* more awkward in .NET 3.5, but
// still simpler than doing it by hand.
string text = string.Join(", ", maquinasNoEncontradas);
System.Diagnostics.Trace.WriteLine("Máquinas no encontradas: " + text);
throw new InvalidOperationException("Máquinas no encontradas: " + text);
}
You could potentially build the comma-separated version and then test whether that's an empty string... but I'm not sure I would, to be honest.
string.Join(", ", gruposCompletos
.SelectMany(x => x.Servidores)
.Select(x => x.Nombre)
.Concat(maquinasSeleccionadas)
.Where(x => !ContieneServidor(datosGruposServidores, x))
.ToArray());

Resources