Using Multiple Databases within a controller asp.net mvc - c#

I have two separate VS Solutions both work fine accessing the databases associated with them.
How ever I need to look up some details from the other database to be displayed in the other solution.
Ive added the second connection string to the web.config and then added the context to my DAL:
namespace RACentral.DAL
{
public class RACentralContext : DbContext
{
public RACentralContext()
: base("RACDev")
{
}
public DbSet<RiskAssessment> RiskAssessments { get; set; }
public DbSet<Hazard> Hazards { get; set; }
public DbSet<PPE> PPEs { get; set; }
public DbSet<RiskAssessmentPPE> RiskAssessmentPPEs { get; set; }
public DbSet<PeopleExposed> PeopleExposeds { get; set; }
public DbSet<RiskAssessmentPeopleExposed> RiskAssessmentPeopleExposeds { get; set; }
public DbSet<RiskAssessmentHazard> RiskAssessmentHazards { get; set; }
public DbSet<ControlMeasure> ControlMeasures { get; set; }
public DbSet<Severity> Severitys { get; set; }
public DbSet<Likelihood> Likelihoods { get; set; }
public DbSet<AddControlMeasure> AddControlMeasures { get; set; }
public DbSet<Type> Types { get; set; }
public DbSet<SubType> SubTypes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
public class PeopleContext : DbContext
{
public PeopleContext()
: base("PeopleContext")
{
}
public DbSet<Person> People { get; set; }
}
}
I get an error in the controller
'Not set to an instance of an object,'
Am trying to access it in my controller as follow:
public class RiskAssessmentController : Controller
{
private RACentralContext db = new RACentralContext();
private PeopleContext Peopledb = new PeopleContext();
public ViewResult StartRA()
{
var user = User.Identity.Name;
string userName = user.Substring(7);
var test = Peopled.Person.FirstOrDefault(x => x.PersonId == 1) //Error here
StartRiskAssessmentViewModel viewModel = new StartRiskAssessmentViewModel
{
RiskAssessment = new RiskAssessment(),
Assessor = userName,
};
return View(viewModel);
}
}

Related

How to cast an object into type of another variable in C#

I'm working on an entity framework project and I'm trying to form a generic structure for adding joins to my table.
class BrowseCONTACTS_BASE : MyBrowseFrm<CONTACTS_BASE>
{
public BrowseCONTACTS_BASE()
{
MyInitialize();
}
public void MyInitialize()
{
//Here I may have more joins
MyAddJoins<ORDERS>("CONTACTS_BASE", "CB_REFNO", "ORDERS", "OR_REFNO", "OR_REFNO");
}
}
On the parent class MyBrowseFrm
partial class MyBrowseFrm<TEntity>:Form where TEntity:class
{
}
I have the following:
MyAddJoins Function that I call from the child class above
protected void MyAddJoins<TTable>(string pParent, string pParentKey, string pChild, string pChildKey,
string pDisplayField) where TTable:class, new()
{
var a = new TTable();
var item = new MyJoins<dynamic>
{
Parent = pParent,
Child = pChild,
ParentKey = pParentKey,
ChildKey = pChildKey,
DisplayField = pDisplayField,
ChildTable = a
};
MyBdJoins.Add(item);
}
//A list to store Joins added from the child table
private List<MyJoins<dynamic>> MyBdJoins;
protected struct MyJoins<TTable> where TTable : class
{
public string Parent;
public string ParentKey;
public string Child;
public string ChildKey;
public string DisplayField;
public TTable ChildTable;
}
Ok this is the part where I'm stuck, The following code will run when I press the search button.
private void MyGenerateQuery()
{
//Here I cast my Context to CONTACTS_BASE
var loContext = (DbSet<TEntity>)Context.GetPropValue(boName);
foreach (var join in MyBdJoins)
{
loContext
.Join(
(DbSet<ORDERS>)Context.GetPropValue(join.Child),
par => par.GetPropValue(join.ParentKey),
chld => chld.GetPropValue(join.ChildKey),
(par, chld) => new { GetPropValue = chld.GetPropValue(join.DisplayField) }
);
}
myGridView1.DataSource = loContext.ToList();
}
The code above at the part where it is:
(DbSet<ORDERS>)Context.GetPropValue(join.Child)
Here what I want to do is:
(DbSet<TTable>)Context.GetPropValue(join.Child)
of course, the above code gives me an error.
Note: in my code TEntity is CONTACTS_BASE and TTable is ORDERS
so how do I cast this object to type TTable
where it is in MyJoins Structure
public TTable ChildTable;
EDIT:
public partial class ORDERS
{
public int OR_REFNO { get; set; }
public string OR_PROD_CODE { get; set; }
public Nullable<DateTime> OR_DATE { get; set; }
public Nullable<int> OR_M_REFNO { get; set; }
public virtual CONTACTS_BASE CONTACTS_BASE { get; set; }
public virtual ORDER_TYPES ORDER_TYPES { get; set; }
}
public partial class CONTACTS_BASE
{
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public CONTACTS_BASE()
{
this.ORDERS = new List<ORDERS>();
}
public int CB_REFNO { get; set; }
public string CB_NAME { get; set; }
public string CB_ID_NO { get; set; }
public string CB_AGE { get; set; }
public Nullable<decimal> CB_TEL_NO { get; set; }
public string CB_EMAIL { get; set; }
public Nullable<DateTime> CB_ENROLL_DATE { get; set; }
public Nullable<DateTime> CB_START_DATE { get; set; }
public Nullable<DateTime> CB_END_DATE { get; set; }
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual IList<ORDERS> ORDERS { get; set; }
}

Include is not available during testing

I have a section of code in my MVC controller that works fine during run-time, but during testing fails. I do a call to the context with an include. During run-time, I can check thisCall and see that thisCall.CallForContentCustomForm is not null. But debugging during testing, it is null.
My models:
public partial class CustomForm : BaseEntity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid CustomFormId { get; set; }
//...
}
public class CallForContent : BaseEntity
{
[Key, ForeignKey("CallForContentResource"), DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid CallForContentId { get; set; }
//...
public Guid CallForContentFormId { get; set; }
[ForeignKey("CallForContentFormId")]
public CustomForm CallForContentCustomForm { get; set; }
}
In my controller:
public partial class ProjectController : BaseController
{
private IMkpContext db;
#region "Constructor"
public ProjectController()
{
db = new MkpContext();
}
public ProjectController(IMkpContext dbContext)
{
db = dbContext;
}
#endregion
public virtual ActionResult callforcontentedit(Guid? id)
{
var thisCall =
db.CallForContent
.Include(cfc => cfc.CallForContentCustomForm)
.Include(cfc => cfc.Project)
.FirstOrDefault(cfc => cfc.CallForContentId == id);
// At this point during run-time thisCall.CallForContentCustomForm has a value,
// but is null during testing
// This row does return the expected result during testing.
var customForms = db.CustomForms.Where(c => c.IsActive && c.CustomFormId == thisCall.CallForContentFormId);
if (thisCall == null) return RedirectToAction("Index", "Submission");
var viewModel = Mapper.Map<CallForContentViewModel>(thisCall);
// ...
ViewBag.Title = viewModel.CallForContentCustomForm.FormName; // Fails here during tests
}
}
In my testing setup, I do add data to the FakeDbContext for the CustomForm table.
var newCallForContentForm = FakeCallForContentForm(newProfile.ProfileId);
fakeDb.CustomForms.Add(newCallForContentForm);
//...
var newCallForContentProposalForm = FakeCallForContentProposalForm(newProfile.ProfileId);
fakeDb.CustomForms.Add(newCallForContentProposalForm);
My Test:
[TestMethod]
public void Project_CallForContent_Test()
{
// Arrange
var fakeDb = TestFakes.SetupFakeDbContext();
var controller = TestFakes.ProjectController(fakeDb);
// Act
var result = controller.callforcontentedit(fakeDb.CallForContent.FirstOrDefault().CallForContentId) as ViewResult;
// Assert
Assert.IsNotNull(result);
}
Here is what my context looks like:
public class FakeMkpContext : AuditDbContext, IMkpContext
{
#region Constructors
static FakeMkpContext()
{
Database.SetInitializer<FakeMkpContext>(null);
}
public FakeMkpContext() : base("Name=FakeMkpContext")
{
this.Profile = new FakeProfileSet();
}
#endregion
#region Property (Dbset)
public IDbSet<Address> Address { get; set; }
public IDbSet<Keyword> Keyword { get; set; }
public IDbSet<CustomForm> CustomForms { get; set; }
public IDbSet<SubmittedForm> SubmittedForms { get; set; }
public IDbSet<SubmittedFormData> SubmittedFormData { get; set; }
public IDbSet<Project> Project { get; set; }
public IDbSet<ProjectType> ProjectType { get; set; }
public IDbSet<CustomFieldGroup> CustomFieldGroup { get; set; }
public IDbSet<CustomFormGroup> CustomFormGroup { get; set; }
public IDbSet<CallForContent> CallForContent { get; set; }
#endregion
//...
}
I am not using Moq for the entity framework portion of my tests.

Collections duplicated when trying to update a detached entity's related collection

I have two API calls. GetExam and SaveExam. GetExam serializes to JSON which means by the time I go to save, the entity is detached. This isnt a problem, I can go retrieve the entity by its primary key and update its properties manually.
However, when I do so the exam questions get its current collection duplicated. For example, if examToSave.ExamQuestions had a few questions deleted, and a new one added all selectedExam.exam_question are duplicated and the new one is added in. Eg. if 3 questions existed, I deleted 1 and added 4 there will now be 7.
Domain models:
public partial class exam
{
public exam()
{
this.exam_question = new HashSet<exam_question>();
}
public int ID { get; set; }
public string ExamName { get; set; }
public string ExamDesc { get; set; }
public Nullable<decimal> TimeToComplete { get; set; }
public bool AllowBackStep { get; set; }
public bool RandomizeAnswerOrder { get; set; }
public int Attempts { get; set; }
public virtual ICollection<exam_question> exam_question { get; set; }
}
public partial class exam_question
{
public exam_question()
{
this.exam_answer = new HashSet<exam_answer>();
}
public int ID { get; set; }
public int ExamID { get; set; }
public string QuestionText { get; set; }
public bool IsFreeForm { get; set; }
public virtual exam exam { get; set; }
public virtual ICollection<exam_answer> exam_answer { get; set; }
}
public partial class exam_answer
{
public int ID { get; set; }
public string AnswerText { get; set; }
public int QuestionID { get; set; }
public bool IsCorrect { get; set; }
public virtual exam_question exam_question { get; set; }
}
Save method:
[Route("SaveExam")]
[HttpPost]
public IHttpActionResult SaveExam(ExamViewModel examToSave)
{
using (var db = new IntranetEntities())
{
// try to locate the desired exam to update
var selectedExam = db.exams.Where(w => w.ID == examToSave.ID).SingleOrDefault();
if (selectedExam == null)
{
return NotFound();
}
// Redacted business logic
// Map the viewmodel to the domain model
Mapper.CreateMap<ExamAnswerViewModel, exam_answer>();
Mapper.CreateMap<ExamQuestionViewModel, exam_question>().ForMember(dest => dest.exam_answer, opt => opt.MapFrom(src => src.QuestionAnswers));
Mapper.CreateMap<ExamViewModel, exam>().ForMember(dest => dest.exam_question, opt => opt.MapFrom(src => src.ExamQuestions));
var viewmodel = Mapper.Map<exam>(examToSave);
// Update exam properties
selectedExam.ExamName = viewmodel.ExamName;
selectedExam.ExamDesc = viewmodel.ExamDesc;
selectedExam.AllowBackStep = viewmodel.AllowBackStep;
selectedExam.Attempts = viewmodel.Attempts;
selectedExam.RandomizeAnswerOrder = viewmodel.RandomizeAnswerOrder;
selectedExam.exam_question = viewmodel.exam_question; // DUPLICATES PROPS
// Save
db.SaveChanges();
return Ok(examToSave);
}
}

Entity framework with Web Api returning object

Hi I am new to entity framework. I have following objects
public partial class lr
{
public lr()
{
this.lr_history = new HashSet<lr_history>();
this.people = new HashSet<person>();
}
public int _id { get; set; }
public string name { get; set; }
public string notes { get; set; }
public virtual ICollection<lr_history> lr_history { get; set; }
public virtual ICollection<person> people { get; set; }
In my Web Api controller I have following code
public class lrController : ApiController
{
private CTM db = new CTM();
// GET api/addL
public IEnumerable<lr> Getlr()
{
from a in DbContext.Activities
return db.lr.AsEnumerable();
}
In above Get method it returns lr but i want to return my own object like
lr.id
lr.name
lr_history.description
lrh_history.rate
Can anyone show me how to achieve this? Than
Create a new model:
class HistoryModel
{
public int Id { get; set; }
public string Name { get; set; }
public string HistoryDescription { get; set; }
public string HistoryRate { get; set; }
}
and return that:
public IEnumerable<HistoryModel> Getlr()
{
from a in DbContext.Activities
return db.lr.AsEnumerable()
.Select(x => new HistoryModel
{
Id = x.id,
Name = x.name,
HistoryDescription = x.history.description,
HistoryRate = x.history.rate
});
}
Instade of return db.lr.AsEnumerable();
try this
return db.lr.ToList();

A better way to retrieve EF data and collections

So I have a model that contains a list of models which contains items, and so on, like this:
public partial class CART
{
public CART()
{
//this.CART_DETAIL = new HashSet<CART_DETAIL>();
this.CART_DETAIL = new List<CART_DETAIL>();
}
public int CART_IDE { get; set; }
public int CART_COUNT { get; set; }
public string SHOPPING_CART_IDE { get; set; }
public virtual IList<CART_DETAIL> CART_DETAIL { get; set; }
}
public partial class CART_DETAIL
{
public int CART_DETAIL_IDE { get; set; }
public int CART_IDE { get; set; }
public int CART_DETAIL_COUNT { get; set; }
public Nullable<int> PACK_IDE { get; set; }
public Nullable<int> BACKSTORE_INVENTORY_IDE { get; set; }
public virtual CART CART { get; set; }
public virtual PACK PACK { get; set; }
public virtual BACKSTORE_INVENTORY BACKSTORE_INVENTORY { get; set; }
}
public partial class BACKSTORE_INVENTORY
{
public BACKSTORE_INVENTORY()
{
this.CART_DETAIL = new HashSet<CART_DETAIL>();
this.ORDER_DETAIL = new HashSet<ORDER_DETAIL>();
}
public int BACKSTORE_INVENTORY_IDE { get; set; }
public int INVENT_IDE { get; set; }
public int STORE_IDE { get; set; }
public decimal BACKSTORE_INVENTORY_PRICE { get; set; }
public int BACKSTORE_STOCK_QTY { get; set; }
public decimal BACKSTORE_DISCOUNT { get; set; }
public decimal BACKSTORE_SELLING_PRICE { get; set; }
public virtual INVENTORY INVENTORY { get; set; }
public virtual STORE STORE { get; set; }
public virtual ICollection<CART_DETAIL> CART_DETAIL { get; set; }
public virtual ICollection<ORDER_DETAIL> ORDER_DETAIL { get; set; }
}
When I open a connection and consult the data, everything's fine, but if I retrive the whole data in a view, for example, unless I modify the Hashset to a List and then proceed like this:
CART cart =
db.CART.FirstOrDefault(_item => _item.SHOPPING_CART_IDE == mShoppingCartID && _item.CART_ACTIVE_INDICATOR);
if (cart != null)
{
cart.CART_EXP_TIME = DateTime.Now.AddMinutes(90);
cart.USER_SESSION_IDE = UserSessionManager.GetUserSession().mUserSessionID;
cart.CART_DETAIL = cart.CART_DETAIL.ToList();
foreach (var cartDetail in cart.CART_DETAIL)
{
if(cartDetail.BACKSTORE_INVENTORY_IDE != null)
{
cartDetail.BACKSTORE_INVENTORY =
db.BACKSTORE_INVENTORY.First(_item => _item.BACKSTORE_INVENTORY_IDE == cartDetail.BACKSTORE_INVENTORY_IDE);
cartDetail.BACKSTORE_INVENTORY.INVENTORY =
db.INVENTORY.Find(cartDetail.BACKSTORE_INVENTORY.INVENT_IDE);
cartDetail.BACKSTORE_INVENTORY.INVENTORY.CARD =
db.CARD.Find(cartDetail.BACKSTORE_INVENTORY.INVENTORY.CARD_IDE);
}
else
{
cartDetail.PACK = db.PACK.First(_item => _item.PACK_IDE == cartDetail.PACK_IDE);
}
}
db.SaveChanges();
}
I get the following error: CS0021: Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.ICollection<MyApp.Models.DAL.Entities.CART_DETAIL>' which I understand is because the ICollection does not afford indexing, and then I get The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. for items that I forgot to retrive.
So my question: what makes this happen? Is there a way to retrieve all the data at once without having to get all specific items separately? A better way to do things?
What are you trying to achieve form the above code?
I am struggling to follow what your end goal is but would something along these lines be what you are looking for:
public List<Cart> GetAllInCart()
{
return db.CART.Where(a => a.Cart_IDE == CartIDE)
.Include(x => x.Cart_Detail)
.Include(x => x.Cart_Detail.Pack)
.Include(x => x.Cart_Detail.Backstore_Inventory)
.ToList()
}
I hope this helps :)

Categories

Resources