Crystal Report Error: The data source object is invalid - crystal-reports

Am Trying to Print out a student Identity Card using crystal report but all what i could get was this error popping up The data source object is invalid.
Guys please help me to check on this code if am making any mistake...
this is the model
public class CardModel
{
// Properties
public string Department { get; set; }
public string ExpiryDate { get; set; }
public string FirstName { get; set; }
public Sex Gender { get; set; }
public Guid Id { get; set; }
public string MiddleName { get; set; }
public string RegistrationNo { get; set; }
public byte[] SecuritySign { get; set; }
public byte[] StudentPhoto { get; set; }
public string Surname { get; set; }
}
public static class CardModelExtention
{
public static CardModel ToCardModel(this Student identity)
{
return new CardModel
{
Id = identity.Id,
FirstName = identity.FirstName,
MiddleName = identity.MiddleName,
Surname = identity.Surname,
StudentPhoto = identity.Photo.RawPhoto,
SecuritySign = identity.SecuritySignature.RawSignature,
Gender = identity.Sex,
ExpiryDate = identity.ExpiryDate,
Department = identity.Department.DepartmentName,
RegistrationNo = identity.RegistrationNo
};
}
}
and here is the service am using to pull the information from database
public class StudentService : IStudentService
{
ERMUoW _ow;
public StudentService()
{
_ow = new ERMUoW();
}
public CardModel GetStudentById(Guid id)
{
CardModel obj3 = new CardModel();
Student student = _ow.Students.GetAllIncluding(new Expression<Func<Student, object>>[] { st => st.Photo, st => st.Signature, st => st.SecuritySignature, st => st.Department }).Where(x => x.Id == id).SingleOrDefault();
var cardInfo = student.ToCardModel();
return cardInfo;
}
}
public interface IStudentService
{
CardModel GetStudentById(Guid id);
}
This is it and everything around here is working fine and am getting the data very well but when I send it to the method in my contrller that generate the identity card I get that error message
this is the code that generate the card using crytal report
public ActionResult PrintCard(Guid id)
{
var student = _studentCardService.GetStudentById(id);
ReportDocument read = new ReportDocument();
read.Load(Server.MapPath("~/Reports/rpt_StudentCard.rpt"));
read.SetDataSource(student);
Response.Buffer = false;
Response.ClearContent();
Response.ClearHeaders();
try
{
Stream stream = read.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/pdf", "StudentIdentityCard.pdf");
}
catch (Exception ex)
{
throw ex;
}
}
I will really Appreciate your help thank you...

The data source have to be a List of elements... not a single element.

Related

Asp .net core web api Entity Framework 5.0 Lazy loading

i have the following client model that has a relation with orders and BloodType tables:
public partial class Client
{
public Client()
{
ClientOrders = new HashSet<ClientOrder>();
}
public long ClientId { get; set; }
public string Name { get; set; }
public string PhoneNumber { get; set; }
public long BloodTypeId { get; set; }
public virtual BloodType BloodType { get; set; }
public virtual ICollection<ClientOrder> ClientOrders { get; set; }
}
when i try the following code to lazy load the orders and the BloodType it's not rendering them and it return the as empty list and null value.
here's my code:
[HttpGet]
[Route("clients-orders")]
public async Task<IActionResult> GetClientsOrders()
{
try
{
var result = await _trainingContext.Clients.FromSqlRaw("Exec getClients").ToListAsync();
var clientsOrders = new List<Client>();
foreach (var client in result)
{
Client currentClient = new Client()
{
ClientId = client.ClientId,
BloodTypeId = client.BloodTypeId,
PhoneNumber = client.PhoneNumber,
ClientOrders = client.ClientOrders,
BloodType = client.BloodType
};
clientsOrders.Add(currentClient);
}
return Ok(clientsOrders);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
Any solution would be very appreciated,
Thank you!

DbContext is not giving any data from database

I have two sets of codes. The first one doesn't give me the list of data but the second on does. Please see codes below:
First Code:
Model
public class Student
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}
DataConnection
public class DataConnection : DbContext
{
public DataConnection()
: base("DefaultConnection")
{
}
public DbSet<Student> Students { get; set; }
}
Interface
public interface IStudent
{
List<Student> StudentList();
void InsertStudent(Student student);
void UpdateStudent(Student student);
Student GetStudentById(int id);
void DeleteStudent(int id);
}
Concrete
readonly DataConnection _context;
public StudentConcrete()
{
_context = new DataConnection();
}
public List<Student> StudentList()
{
var studentList = (from s in _context.Students select s).ToList();
return studentList;
}
Second Code
Concrete
readonly DataConnection _context;
public StudentConcrete()
{
_context = new DataConnection();
}
public List<Student> StudentList()
{
SqlConnection xxx = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
var cmd = new SqlCommand("GetAllStudents", xxx);
var da = new SqlDataAdapter(cmd);
var ds = new DataSet();
da.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
return (from DataRow row in ds.Tables[0].Rows
select new Student()
{
Age = Convert.ToInt32(row["Age"]),
FirstName = row["FirstName"].ToString(),
Gender = row["Gender"].ToString(),
LastName = row["LastName"].ToString()
}).ToList();
}
else
{
return null;
}
}
I would like to get the data using the first code but I don't know where I get it wrong. My SP is just to get the students.
I suspected that maybe you are retrieving the records from another table somehow. Would you try to add Table attribute for Student entity.
using System.ComponentModel.DataAnnotations.Schema;
[Table("Students")]
public class Student
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}

How to cast my Linq query to the expected Web API return type

My .Net Core Web API call is not returning values to the browser, but hanging the browser.
I have these models:
public class Status
{
public long StatusId { get; set; }
public long UserId { get; set; }
public string Body { get; set; }
public virtual User User { get; set; }
}
public class User
{
public long UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public virtual ICollection<Status> Statuses { get; set; }
}
My Status controller's Get functions look like this:
[HttpGet]
public IEnumerable<Status> GetAll()
{
var rv = _context.Statuses.ToList();
return rv;
}
When I GET the API endpoint, I get the first record, then the browser hangs (keeps loading) and the rest of the data never comes through.
Stepping into my code, I see that rv is getting populated with all of the records, but we have the problem of the User having Statuses and then the Statuses have a User and so on - circular reference.
Ok, so let's try this in the controller so we don't get the Statuses from User:
var rv = _context.Statuses.Select(s => new
{
StatusId = s.StatusId,
UserId = s.UserId,
Body = s.Body,
User = from u in _context.Users
select new
{
UserId = u.UserId,
Name = u.Name,
Email = u.Email,
}
}
).ToList();
return rv;
Problem is rv is an anonymous type and I can't figure out how to successfully type it to the IEnumerable<Status> return type, even though it is the same as the model (excepting the missing Statuses in the User). Or do I change the return type and what to?
You could use dynamic as return type or you can create a custom class to save the projection of the query you need:
[HttpGet]
public dynamic GetAll()
{
var rv = _context.Statuses.Select(s => new
{
StatusId = s.StatusId,
UserId = s.UserId,
Body = s.Body,
User = from u in _context.Users
select new
{
UserId = u.UserId,
Name = u.Name,
Email = u.Email,
}
}).ToList();
return rv;
}
Also you can return a HttpResponseMessage :
public HttpResponseMessage Get()
{
var rv = _context.Statuses.Select(s => new
{
StatusId = s.StatusId,
UserId = s.UserId,
Body = s.Body,
User = from u in _context.Users
select new
{
UserId = u.UserId,
Name = u.Name,
Email = u.Email,
}
}).ToList();
return Request.CreateResponse(HttpStatusCode.OK, rv);
}
I'd recommend you to use separate ViewModel/DTO class to send data from API controller. Example:
public class StatusModel
{
public long StatusId { get; set; }
public long UserId { get; set; }
public string Body { get; set; }
public virtual User User { get; set; }
}
public class UserModel
{
public long UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public HttpResponseMessage Get()
{
var result = _context.Statuses.Include(e => e.User).Select(e => new StatusModel
{
StatusId = e.StatusId,
UserId = e.UserId,
Body = e.Body,
User = new UserModel
{
UserId = e.User.UserId,
Name = e.User.Name,
Email = e.User.Email,
}
}).ToArray();
return Request.CreateResponse(HttpStatusCode.OK, result);
}

Saving one entity having m-t-m relationship duplicate the other entity in the DB?

I have two entities with many to many relationship, I'm saving one entity that has a list of entities, but they get duplicated
ex:
class GENEntity
{
int Id { get; set; }
string Name { get; set; }
List<GENEntityTab> tabs { get; set; }
}
class GENEntityTab
{
int Id { get; set; }
string Name { get; set; }
List<GENEntity> entities { get; set; }
}
When I save object of GENEntity but as a view model as you'll see next, with a list of two GENEntityTab, those two tabs get inserted (duplicated) in the DB. I'm using Web API and angular
In the Repository, it's only called when I click submit (there are some extra properties):
public static JsonViewData AddOrUpdate(ModelDBContext context, GENEntityViewModel entityVM, string name, string id)
{
try
{
var entity = context.Entities.SingleOrDefault(x => x.Id == entityVM.Id);
if (entity == null)
{
entity = new GENEntity();
entity.InjectFrom(entityVM);
context.Entities.Add(entity);
}
else
{
entity.DateUpdated = DateTime.Now;
entity.InjectFrom(entityVM);
}
entity.CreatedById = new Guid(id);
entity.LastUpdatedById = new Guid(id);
context.SaveChanges();
return new JsonViewData { IsSuccess = true, Message = "Created Successfully" };
}
catch (Exception ex)
{
return new JsonViewData { IsSuccess = false, Message = ex.Message };
}
}
the view models:
public class GENEntityTabViewModel
{
public long Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<GENEntity> Entities { get; set; } = new List<GENEntity>();
public GENEntityTabViewModel()
{
}
public GENEntityTabViewModel(GENEntityTab entityTab)
{
Id = entityTab.Id;
Name = entityTab.Name;
Description = entityTab.Description;
Entities = entityTab.Entities;
}
}

EF7 Read Master Detail Records

I'm trying to get my head around EF7 by writing a simple master-detail relationship to a sqlite database. Saving works fine, reading however gives me headaches:
Here are my Entities:
public class Message
{
public int MessageId { get; set; }
public string Name { get; set; }
public List<MessagePart> MessageParts { get; set; }
}
public class MessagePart
{
public int MessagePartId { get; set; }
public string Text { get; set; }
public int MessageId { get; set; }
public Message Message { get; set; }
}
createMessage() does what it is supposed to:
static void createMessages()
{
using (var db = new TestContext())
{
var m1 = new Message
{
Name = "train_arrives_in_x_minutes",
MessageParts = new List<MessagePart>()
{
new MessagePart {
Text = "Train arrives in 5 minutes"
},
new MessagePart {
Text = "Zug faehrt in 5 Minuten ein",
}
}
};
var m2 = new Message
{
Name = "train_out_of_service",
MessageParts = new List<MessagePart>()
{
new MessagePart {
Text = "train is out of service"
},
new MessagePart {
Text = "Kein Service auf dieser Strecke",
}
}
};
db.Messages.Add(m1);
db.Messages.Add(m2);
var count = db.SaveChanges();
Console.WriteLine("{0} records saved to database", count);
}
}
Reading from an existing database reads the master record fine, but the detail recordset pointer stays null.
static void readMessages()
{
using (var db = new TestContext())
{
foreach (Message m in db.Messages)
{
Console.WriteLine(m.Name);
// exception here: m.MessageParts is always null
foreach(MessagePart mp in m.MessageParts)
{
Console.WriteLine("mp.Text={0}", mp.Text);
}
}
}
}
Is there anything I can do to force those messagesparts to load? I've worked with other (Python) ORMs before and never had this problem before. Is this a problem with Lazy Loading? I tried to fetch those childrecords using a LINQ statement, that didn't help either. Everything looks good in the database though.
If you want to enable LazyLoading you need to enable LazyLoading (should be enabled by default) and make your property virtual:
public TestContext()
: base(Name = "ConntextionName")
{
this.Configuration.ProxyCreationEnabled = true;
this.Configuration.LazyLoadingEnabled = true;
}
And your models shuodl look like:
public class Message
{
public int MessageId { get; set; }
public string Name { get; set; }
public virtual ICollection<MessagePart> MessageParts { get; set; }
}
public class MessagePart
{
public int MessagePartId { get; set; }
public string Text { get; set; }
public int MessageId { get; set; }
public virtual Message Message { get; set; }
}
If you do not want to use LazyLoading, you can load related entities using eager loading:
using System.Data.Entity;
using (var db = new TestContext())
{
int messageId = ....;
Message message = db.Messages
.Where(m => m.MessageId == messageId)
.Include(m => m.MessageParts) // Eagerly load message parts
.FirstOrDefault();
// Your message and all related message parts are now loaded and ready.
}
For more information, please have a look at this site.