I'm building an VS C# 5-Tier solution with UI, Service, Logic, Business-Data and Data-Layers projects. I'm using WCF and EF6, with EF6 loaded into the UI, the Service and the Data layers. I'm using ADO.NET for Entities in the Data Layer, and my Entity was built as Database-first.
I have a DataGridView control on my UI Win-Form and I want to view all or select members of my organization in the DataGridView on demand.
When I instantiate my Service in the UI, my code works to get the requested data rows to return from the data layer (EF query), back through logic layer, to Service layer.
But when I try to use the Service layer's returned object, I receive the "Object reference not set to an instance of an object" error.
My goal is to use the returned list as the data source for a Binding Source control for my DataGridView. I also need help in understanding how to get the I-List object to expose to its object level. Any help would be appreciated, thanks.
** Service Contract: **
***
[DataContract]
public class MemberList
{
[DataMember]
public IList MembersInList { get; set; }
}
***
[DataContract]
public class Member
{
[DataMember]
public int MemberID { get; set; }
[DataMember ]
public string Last_Name { get; set; }
[DataMember]
public string First_Name { get; set; }
[DataMember]
public string MidInit { get; set; }
[DataMember]
public string Email_Address { get; set; }
}
***
** Here's my datalayer: **
***
public MemberBDOList FillMemberGrid()
{
MemberBDOList myDAO = new MemberBDOList();
using (var afDBEntities = new AFDBEntities())
{
var members = afDBEntities.Members.ToList(); // gets all 68 Members in MSSQL table
if (members != null)
{
myDAO.MembersBDOInList = members;
}
}
return myDAO as MemberBDOList; //returns all 68 Members to Logic Layer as collection
}
***
** Here's my Service.cs object (Service layer): **
***
public MemberList FillMemberGrid()
{
MemberBDOList objMembersBDO = null;
try
{
objMembersBDO = new MemberBDOList();
objMembersBDO = memberLogic.FillMemberGrid();
}
catch (Exception e)
{
var msg = e.Message;
var reason = "FillMemberGrid Exception";
throw new FaultException<MemberFault>(new MemberFault(msg), reason);
}
if (objMembersBDO.MembersBDOInList == null)
{
var msg = string.Format("No members were found.");
var reason = "FillMemberGrid: Empty Entity Member";
throw new FaultException<MemberFault>(new MemberFault(msg), reason);
}
var objMembers = new MemberList();
TranslateMembersBDOToMembersDTO(objMembersBDO, objMembers); // method below
return objMembers.MembersInList as MemberList;
}
private void TranslateMembersBDOToMembersDTO(MemberBDOList objMembersBDO, MemberList objMembers)
{
objMembers.MembersInList = objMembersBDO.MembersBDOInList;
}
}
***
** Here is the Business-Data object: **
***
[Serializable]
public class MemberBDOList
{
public IList MembersBDOInList { get; set; }
}
***
** And here are the UI methods: **
***
MemberServiceProxy.Member member;
MemberServiceProxy.MemberList memberList;
private void btnFillMemberGrid_Click(object sender, EventArgs e)
{
BindingSource bSrc = new BindingSource();
int M = 0;
try
{
M = 1;
memberList = GetMemberList();
M = 3;
//fails here with "Object reference not set to an instance of an object."
bSrc.DataSource = memberList.MembersInList.ToList(); // fails with or without To-List
M = 5;
adgView.DataSource = bSrc;
M = 7;
adgView.Refresh();
}
catch (Exception ex)
{
}
}
private MemberList GetMemberList()
{
var results = new MemberList();
int M = 0;
try
{
M = 1;
var client = new MemberServiceClient();
M = 3;
//go get the member list from Data Layer EF
results = client.FillMemberGrid();
return results;
}
catch (Exception ex)
{
return results;
}
}
***
** Code update in Data Layer and in Service Layer - to translate the DataContract "Members" object at the data member level in List. Showing DAL layer here. **
***
public MembersBDO FillMemberGrid()
{
var membersBDO = new MembersBDO();
var memberBDO = new MemberBDO();
int M = 0;
try
{
M = 1;
using (var afDBEntities = new ACTSFactsDBEntities())
{
M = 3;
var members = afDBEntities.Members.ToList(); // gets all 68 Members in MSSQL table (Entity is Database-first)
M = 5;
// if (members != null)
// {
// M = 7;
// membersBDO.MemberBDOList = members; //this works with the IList data contract,
// //but the IList data, unconverted, belongs to the data layer - no conversion is done
// //here from DAL data types to BDO data types at the members[index].(columnName) level
// }
//so, (below) this solves that issue, and converts to the [DataMember] level (the data row's columns)
//for each [DataContract] Member in "members" - the List<Member> object which belongs to the data layer project.
//
M = 9;
if (members != null) //the data layer object has rows, good.
{
int n = 0;
foreach (Member m in members) //read through each data layer EF Member type in "members" list
{
memberBDO = new MemberBDO() //instantiate a new MemberBDO type to translate the DAL member.Columns to
{
MemberID = m.MemberID, //each DAL column must be translated to its matching BDO type
Last_Name = m.Last_Name,
First_Name = m.First_Name,
MidInit = m.MidInit,
Email_Address = m.Email_Address,
Home_Phone = m.Home_Phone,
Cell_Phone = m.Cell_Phone,
Mailing_Address = m.Mailing_Address, etc
};
membersBDO.memberBDOList.Add(memberBDO);
memberBDO = null;
n += 1;
if (n > 60) break; // my code breaks at request for all 68 rows with error
// - "MaxReceivedMessageSize" (65536 bytes) property exceeded
}
}
M = 11;
return membersBDO; //returning 61 of my 68 Members works to Service layer, through Logic Layer
}
}
***
** Changes to code in Service layer: **
***
public Members FillMemberGrid()
{
MembersBDO objMembersBDO = null;
try
{
objMembersBDO = new MembersBDO();
objMembersBDO = memberLogic.FillMemberGrid();
}
catch (Exception e)
{
var msg = e.Message;
var reason = "FillMemberGrid Exception";
throw new FaultException<MemberFault>(new MemberFault(msg), reason);
}
if (objMembersBDO == null)
{
var msg = string.Format("No members were found.");
var reason = "FillMemberGrid: Empty Entity Member";
throw new FaultException<MemberFault>(new MemberFault(msg), reason);
}
var objMembers = new Members();
TranslateMembersBDOToMembersDTO(objMembersBDO, objMembers); //a private method defined below
return objMembers as Members;
}
private void TranslateMembersBDOToMembersDTO(MembersBDO objMembersBDO, Members objMembers)
{
//objMembers.MemberList = objMembersBDO.MemberBDOList;
foreach (MemberBDO mBDO in objMembersBDO.memberBDOList)
{
Member m = new Member();
TranslateMemberBDOToMemberDTO(mBDO, m); //calling the same translate code that translates the return of a one member request
objMembers.MemberList.Add(m);
m = null;
m = new Member();
}
}
***
** Changes to [DataContract] Members class in IMemberService.cs **
***
[DataContract]
public class Members
{
[DataMember]
public List<Member> MemberList { get; set; } = new List<Member>();
}
***
** Here's the change to class MembersBDO in the Business Domain Object layer **
***
[Serializable]
public class MembersBDO
{
public List<MemberBDO> memberBDOList { get; set; } = new List<MemberBDO>();
}
***
Thanks MBD, for your help in resolving my issue. We all need a sounding board, and your suggestion put me on the right track. See my updates for the answer that I finally came to use in the application. Still got issues, but not this one.