How to join tables using include with entity SQL - c#

I will try to describe my issue in details.I have the following scenario.
1.) I have 3 tables : business, customoffice(Custom Office) and cusdesc(custom office description)
The relationship is that a business has on customoffice and one customoffice has many cusdesc.
The table business has a field customofficeno which is a foreign key to the field cuscode of the customoffice table.The table cusdesc has a field cuscode which is a foreign key to the field cuscode of the customoffice table.
The objective is to select a business including the custom office and custom office description using entity framework.
2.) Code
I have a procedure FillData which fills a datagrid. My objective is to display fields from the 3 tables. I managed to display data from tables "Business" and "Customoffice" but i need to display the description of a custom office via table "cusdesc" and be more specific the field "CSNAME".
3.) My issue is that when I include the ("CUSTOMSOFFICE.CUSDESC") the results do not contain data from table "CUSDESC" but only how many records much the criteria so I cannot access the field "CSNAME"
Hereafter is the procedure:
using (var _context = new ReftabEntities())
{
try
{
SetGlobalValues();
ObjectQuery<BUSINESS> q_business = _context.BUSINESS.Where("it.BUSINESSNO=" + int.Parse(pv_businessno)).Where(string.Format("(it.BUSINESSSTART <= DATETIME'{0:yyyy-MM-dd HH:mm}') and (it.BUSINESSCLOSED >= DATETIME'{0:yyyy-MM-dd HH:mm}')", pv_date)).Include("CUSTOMSOFFICE").Include("CUSTOMSOFFICE.CUSDESC");
gvBusinessList.Caption = "Total records selected: " + q_business.Count();
gvBusinessList.DataSource = q_business;
gvBusinessList.DataBind();
}
catch (Exception e)
{
errorPopup.Text = e.Message;
errorPopup.ShowOnPageLoad = true;
}
finally
{
_context.Dispose();
}
}
}
Can you please give a hint what I do wrong.
Thanks in advance.

The Include operator just asks EF to load a related entity with the query. If you don't use "Include", EF will only extract the properties of BUSINESS and will not extract the properties of the CUSTOMSOFFICE. There is no need for the "Include("CONSOMSOFFICE.CUSDESC")" since you already loaded the entire CUSTOMSOFFICE entity in the first Include.
I see that you're binding the result to the grid view, and if I understand correctly, the issue is that the "CUSTOMSOFFICE.CUSDESC" is not being displayed in the gridview. I believe this is because the gridview tries to render its representation of the "CUSTOMSOFFICE" object itself, since that's the direct property of the items you are binding. To have more control over the "columns" of your gridview, I suggest using LINQ to transform the results of your query into what you explicitly want to display.
I am assuming that BUSINESSNO, BUSINESSSTART, and BUSINESSCLOSED are properties of your Business entity itself, and that BUSINESSNO is the Primary Key. Let me rewrite your query into this:
var q_business = _context.BUSINESS.Include(b=>b.CUSTOMSOFFICE)
.Where(p => p.BUSINESSNO == int.Parse(pv_businessno)
&& p.BUSINESSSTART <= DateTime.Parse(pv_date)
&& p.BUSINESSCLOSED >= DateTime.Parse(pv_date) )
.FirstOrDefault();
This query would extract the details of the Business (including the related CUSTOMSOFFICE details) that matches the given pv_businessno and falls within your date criteria. But you can't bind this to your gridview yet because you might encounter the same problem where the CUSTOMSOFFICE.DESC is not displayed. To ensure proper display, you must identify what properties you want to include. For example, if you only want to display the set of properties below:
BUSINESS.BUSINESSNO
BUSINESS.BUSINESSNAME
BUSINESS.CUSTOMSOFFICE.CUSCODE
BUSINESS.CUSTOMSOFFICE.CUSDESC
You should transform your output to explicitly and immediately include these properties.
var q_business = _context.BUSINESS.Include(b=>b.CUSTOMSOFFICE)
.Where(b => b.BUSINESSNO == int.Parse(pv_businessno)
&& b.BUSINESSSTART <= DateTime.Parse(pv_date)
&& b.BUSINESSCLOSED >= DateTime.Parse(pv_date) )
.Select(b => new {BusinessNo = b.BUSINESSNO,
BusinessName = b.BUSINESSNAME,
CustomsOfficeCode = b.CUSTOMSOFFICE.CUSCODE,
CustomsOfficeDesc = b.CUSTOMSOFFICE.CUSDESC } ) //This Select statement creates a new anonymous type that has Businessno, BusinessName, CustomsOfficeCode, and CustomsOfficeDesc properties
.FirstOrDefault();
When you bind this to your gridview, it should be able to display the value of the CUSDESC property.

Related

Checking duplication using LINQ in collection

I have function which inserts record in database. I want to make sure that there are no duplicate entries in database. Function first checks if there is query string parameter. If there is, then it acts like edit mode otherwise insert mode. There is a function which can return currently added records in database. I need to check duplication based on two columns before insertion in database.
myService = new myService();
myFlow mf = new myFlow();
if (!string.IsNullOrEmpty(Request["myflowid"]))
{
mf = myService.Getmyflow(Convert.ToInt32(Request["myflowid"]));
}
int workcount = 0;
int.TryParse(txtWorkCount.Text, out workcount);
mf.Name = txtName.Text.Trim();
mf.Description = txtDescription.Text.Trim();
mf.FunctionCode = txtFunctioneCode.Text.Trim();
mf.FunctionType = txtFunctioneType.Text.Trim();
mf.WorkCount = workcount;
if (mf.WorkFlowId == 0)
{
mf.SortOrder = 0;
mf.Active = true;
mf.RecordDateTime = DateTime.Now;
message = "Saved Successfully";
}
else
{
_editMode = true;
message = "Update Successfully";
}
}
int myflowId = mfService.AddEditmyflow(mf);
I want to check duplication based on functiontype and functioncode. Another function mfService.Getmyflows() can return currently added records in database.
How can I check duplication using Linq?
First of all, what database do you use? Many databases support upsert behavior (update or insert depending of was data found or not). For example, MERGE in ms sql, MERGE in oracle, INSERT .. ON DUPLICATE in mysql and so on. This could be preferred solution. Upsert is usually an atomic operation.
In your particular case do you you transactions? Are you sure no one will insert data after you ensured about duplicates but before you have inserted your record? Example:
#1 thread #2 thread
look for duplicates
... look for duplicate
no duplicates found ...
no duplicates found
insert data_1
insert data_1
This will end up with duplicates you trying to avoid.
According to your code you populating data from GUI and adding only one item.
If you have access to myService code you could add method to query item by your two columns, instead of querying all items via mfService.Getmyflows() and looking through this collection inside your code. It would be more performant (especially if you have indexes in that columns) and more memory efficient.
And finally, existing of a single element inside collection can be easily done:
var alreadyExist = mfService.Getmyflows()
.Any(x => x.Column1 == value1 && x.Column2 == value2);

Copy a text field data into a look field type

I am new in coding world :) it would be helpful if somebody can help me with my below query.
We have created two custom entity called Sector and Sub sector which are having an 1:N relationship with Account. Since they are relation fields hence they are lookup type and populated on the Account form.
On another part, we have InsideView( 3rd party tool) integrated with our Contact and account form. We have mapped certain fields from Inside view with CRM fields to update the data from the inside view when it is being synced however Inside view does not support Lookup type field hence we cannot map lookup field type data.
We discovered this barrier recently when we tried to map our custom entity (sector and Subsector) with inside view. Since we cannot map lookup field type we thought to have two text field instead and map it with Inside view. Once data is synced these two text fields will get filled out with the sector and subsector name.
Now, we want to copy information from text fields to the lookup field (custom fields Sector and Sub sector)
thanks in advance for your help :)
Bhavesh
I am not understanding your requirement but you can fill a lookup field with some text.
Use following code:
function setLookupField() {
var context = Xrm.Page.context;
var UserID = context.getUserId();// your id
var UserName=context.getUserName();//your text
var lookupData = new Array();
var lookupItem = new Object()`enter code here`;
//Set the GUID
lookupItem.id = UserID;
//Set the name
lookupItem.name = UserName;
lookupItem.entityType = "systemuser";// entity name of lookup
lookupData[0] = lookupItem;
//If existing value is empty, then set new value
var existingValue = Xrm.Page.getAttribute("new_usercreatedby").getValue();
if (existingValue === null) {
Xrm.Page.getAttribute("new_usercreatedby").setValue([{
id: UserID,
name: UserName,
entityType: "systemuser"
}]);
} else {
return;
}
}

Querying 2 datatables in a dataset

I have 2 datatables named 'dst' and 'dst2'. they are located in the dataset 'urenmat'.
The mayority of the data is in 'dst'. this however contains a column named 'werknemer'. It contains a value which corresponds to a certain row in 'dst2'. This column is named 'nummer'.
What i need is a way to left outer join both datatables where dst.werknemer and dst2.nummer are linked, and a new datatable is created which contains 'dst2.naam' linked to 'dst.werknemer' along with all the other columns from 'dst'.
I have looked everywhere and still can't seem te find the right answer to my question. several sites provide a way using LINQ in this situation. I have tried using LINQ but i am not so skilled at this.
I tried using the 101 LINQ Samples:
http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
urenmat = dataset.
dst = a, b, c, d, werknemer.
dst2 = nummer, naam.
I used the following code from '101'.
var query =
from contact in dst.AsEnumerable()
join order in dst2.AsEnumerable()
on contact.Field<string>("werknemer") equals
order.Field<string>("nummer")
select new
{
a = order.Field<string>("a"),
b = order.Field<string>("b"),
c = order.Field<string>("c"),
d = order.Field<string>("d"),
naam = contact.Field<decimal>("naam")};
I however don't know what to change 'contact' and 'order' to and i can't seem to find out how to save it to a datatable again.
I am very sorry if these are stupid questions but i have tried to solve it myself but it appears i'm stupid:P. Thank for the help in advance!
PS. i am using C# to code, the dataset and datatables are typed.
if you want to produce a projected dataset of dst left outer joined to dst2 you can use this LINQ expression (sorry i don't really work in LINQ query syntax so you'll have to use this lambda syntax instead).
var query = dst.AsEnumerable()
.GroupJoin(dst2.AsEnumerable(), x => x.Field<string>("werknemer"), x => x.Field<string>("nummer"), (contact, orders) => new { contact, orders })
.SelectMany(x => x.orders.DefaultIfEmpty(), (x, order) => new
{
a = order.Field<string>("a"),
b = order.Field<string>("b"),
c = order.Field<string>("c"),
d = order.Field<string>("d"),
naam = x.contact.Field<decimal>("naam")
});
because this is a projected dataset you cannot simply save back to the datatable. If saving is desired then you would want to load the affected row, update the desired fields, then save the changes.
// untyped
var row = dst.Rows.Find(keyValue);
// typed
var row = dst.FindBy...(keyValue);
// update the field
row.SetField("a", "some value");
// save only this row's changes
row.AcceptChanges();
// or after all changes to the table have been made, save the table
dst.AcceptChanges();
Normally if you need to perform loading and saving of (projected) data, an ORM (like entity framework, or LINQ-to-SQL) would be the best tool. However, you are using DataTable's in this case and I'm not sure if you can link an ORM to these (though it seems like it would probably be possible).

Unable to search a SQL database under ASP.NET

I've added a LINQ-SQL link in my website to make objects and after that, I'm trying to write the neccesary code to search into a database.
In my case I am trying to display a column value assigned to another of other column into a DATABASE using the following code but I can't:
Palabras_Definiciones quintanaserena = new Palabras_Definiciones(); // LINQ
if (searchInput.Attributes["value"] == quintanaserena.palabra)
{
Label1.Text = quintanaserena.definiciĆ³n;
}
Am I doing anything wrong?
In the code above, you are not doing any request to the database. You only created the object that has the same definition as your database table.
To query your database, you need to do a query over your DataContext (usually the name of your .dbml file).
MSDN has a good web page to show sample of query. You might want to take a look there: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
Your query would probably look like:
palabrasDataContext dcPalabras = new palabrasDataContext(); //palabrasDataContext would be the name of the DataContext you generated
Palabras_Definiciones quintanaserena = (from palabras in palabrasDataContext
where palabras.palabra == searchInput.Attributes["value"] //palabra is the name of the column
select palabras).FirstOrDefault(); //Using firstorDefault here if you have only one definition per word
if(quintanaserena != null) //FirstorDefault returns null if the resultset was empty
{
label1.Text = quintanaserena.definiciĆ³n;
}

bulk insert and update with ADO.NET Entity Framework

I am writing a small application that does a lot of feed processing. I want to use LINQ EF for this as speed is not an issue, it is a single user app and, in the end, will only be used once a month.
My questions revolves around the best way to do bulk inserts using LINQ EF.
After parsing the incoming data stream I end up with a List of values. Since the end user may end up trying to import some duplicate data I would like to "clean" the data during insert rather than reading all the records, doing a for loop, rejecting records, then finally importing the remainder.
This is what I am currently doing:
DateTime minDate = dataTransferObject.Min(c => c.DoorOpen);
DateTime maxDate = dataTransferObject.Max(c => c.DoorOpen);
using (LabUseEntities myEntities = new LabUseEntities())
{
var recCheck = myEntities.ImportDoorAccess.Where(a => a.DoorOpen >= minDate && a.DoorOpen <= maxDate).ToList();
if (recCheck.Count > 0)
{
foreach (ImportDoorAccess ida in recCheck)
{
DoorAudit da = dataTransferObject.Where(a => a.DoorOpen == ida.DoorOpen && a.CardNumber == ida.CardNumber).First();
if (da != null)
da.DoInsert = false;
}
}
ImportDoorAccess newIDA;
foreach (DoorAudit newDoorAudit in dataTransferObject)
{
if (newDoorAudit.DoInsert)
{
newIDA = new ImportDoorAccess
{
CardNumber = newDoorAudit.CardNumber,
Door = newDoorAudit.Door,
DoorOpen = newDoorAudit.DoorOpen,
Imported = newDoorAudit.Imported,
RawData = newDoorAudit.RawData,
UserName = newDoorAudit.UserName
};
myEntities.AddToImportDoorAccess(newIDA);
}
}
myEntities.SaveChanges();
}
I am also getting this error:
System.Data.UpdateException was unhandled
Message="Unable to update the EntitySet 'ImportDoorAccess' because it has a DefiningQuery and no element exists in the element to support the current operation."
Source="System.Data.SqlServerCe.Entity"
What am I doing wrong?
Any pointers are welcome.
You can do multiple inserts this way.
I've seen the exception you're getting in cases where the model (EDMX) is not set up correctly. You either don't have a primary key (EntityKey in EF terms) on that table, or the designer has tried to guess what the EntityKey should be. In the latter case, you'll see two or more properties in the EDM Designer with keys next to them.
Make sure the ImportDoorAccess table has a single primary key and refresh the model.

Categories

Resources