Consider the following model for a EF 6 entity:
Id (int, nullable:false, identity: true)
Name (string)
Number (string).
I want number to persisted as combination of letter and id field. For example if during insert id valuse is going to be 1, I want number to be A00000001. I tried using DatabaseGenerated attribute on Number but that did not work. Problem is at time of insert EF will not know what identity value is. Is there a way to define a trigger to do so or is there some other method I can achieve this.
Thanks!
If you don't need to save the computed field to the database and are using POCOs for Entities you can just define an unmapped field like this:
[NotMapped]
public string Number
{
get { return Name + Id.ToString(); }
}
Try first inserting the item to the database:
Item myItem = new Item(){Name = "MyName"};
dbcontext.Items.Add(myItem);
dbcontext.SaveChages();
Then bring the item from the database and update it:
Item insertedItem = dbcontext.Items.Single(i => i.Id == myItem.Id);
insertedItem.Number = insertedItem.Name + insertedItem.Id.toString();
dbcontext.SaveChages();
Related
in this case i have custome field namely "Project Phase" then in value based on Lookup Table.
how can i get guid or internal name like 'Entry_d4399450ea69e61180cb00155d18530e' based on Delay value that appear in above image. this internal name i will use for updating data using C# Console.
here my simple code, but it doesn't VALID:
var PrjList = projContext.LoadQuery(projContext.CustomFields.Where(proj => proj.Name == cFieldName));
projContext.ExecuteQuery();
Guid pGuid = PrjList.First().Id;
Console.WriteLine(pGuid);
i finally i got simple linq query in ms project to get internal name of lookup based on custome field. here is my codeand it worked:
var InternalNameLookup = pubProj.CustomFields.LookupEntries.Where(x => x.FullValue == "Delay").First().InternalName;
this code will display internal name "Entry_d4399450ea69e61180cb00155d18530e". this is that i need to update my custome field based on lookup field.
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;
}
}
I'm using entity framework 7 or core 1.0 for my new project. In the products table, ProductName column is set as an alternate key (unique constraint). The problem is that I'm unable to update this column in the database. The code for edit actions is as follows:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(ProductViewModel product, int id, IFormFile ProductImage)
{
try
{
if (ModelState.IsValid)
{
var Product = _products.Find(x => x.ProductID == id).Single();
string tempName = Product.ProductName; //for deleting directory if name has been changed.
Product = _mapper.Map<Product>(product);
//code to replace image file if new file has been uploaded OR
//delete / change directory if the product name has been changed
//goes here
//Insert id again after mapping
Product.ProductID = id;
ProductImage image = _images.Find(m => m.ProductID == id).Single();
image.Hash = FileName;
image.Product = Product;
image.Extension = FileExtension;
image.ProductID = Product.ProductID;
_products.Update(Product);
_images.Update(image);
if (_products.SaveAll() && _images.SaveAll())
{
return RedirectToAction("Index");
}
}
}
catch (Exception ex)
{
_logger.LogDebug(ex.Message);
throw;
}
product.Categories = _categories.GetAll().ToList();
return View(product);
}
I've debugged through all of this and everything is working fine, all other properties are being updated in the database, the ProductName is being updated in memory objects (not the database), the files / folders are being replaced, even the images database table is being updated, but when the product name is changed the return statement inside the SaveAll() if statement isn't executed nor is this particular column in database being updated. Please help!
Ok I've found the answer through Entity Framework Core's Github. Here's the answer:
EF Core currently does not support changing the value of alternate keys. We do have #4073 tracking removing this restriction though.
BTW it only needs to be an alternate key if you want it to be used as the target key of a relationship. If you just want a unique index, then use the HasIndex() method, rather than AlternateKey() . Unique index values can be changed.
Source:
Github
You can't change the column setted as an alternate key.
If you just want a unique index in your table you can use HasIndex with IsUnique, for example:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.HasIndex(u => u.ProductName)
.IsUnique();
}
Indexes are a common concept across many data stores. While their
implementation in the data store may vary, they are used to make
lookups based on a column (or set of columns) more efficient. By
convention, an index is created in each property (or set of
properties) that are used as a foreign key.
Read more about EF Core Indexes
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.
I have 3 tables. A primary EmploymentPlan table with PK GUID EmploymentPlanID and 2 FK's GUID PrevocServicesID & GUID JobDevelopmentServicesID. There are of course other fields, almost exclusively varchar(). Then the 2 secondary tables with the corresponding PK to the primary's FK's.
I am trying to write the LINQ INSERT Method and am struggling with the creation of the keys. Say I have a method like below. Is that correct? Will that even work? Should I have seperate methods for each?
Also, when inserting I didn't think I needed to provide the PK for a table. It is auto-generated, no?
Thanks.
public static void InsertEmploymentPlan(int planID, Guid employmentQuestionnaireID, string user, bool communityJob, bool jobDevelopmentServices, bool prevocServices, bool transitionedPrevocIntegrated, bool empServiceMatchPref)
{
using (var context = MatrixDataContext.Create())
{
var empPrevocID = Guid.NewGuid();
var prevocPlan = new tblEmploymentPrevocService
{
EmploymentPrevocID = empPrevocID
};
context.tblEmploymentPrevocServices.InsertOnSubmit(prevocPlan);
var empJobDevID = Guid.NewGuid();
var jobDevPlan = new tblEmploymentJobDevelopmetService()
{
JobDevelopmentServicesID = empJobDevID
};
context.tblEmploymentJobDevelopmetServices.InsertOnSubmit(jobDevPlan);
var empPlan = new tblEmploymentQuestionnaire
{
CommunityJob = communityJob,
EmploymentQuestionnaireID = Guid.NewGuid(),
InsertDate = DateTime.Now,
InsertUser = user,
JobDevelopmentServices = jobDevelopmentServices,
JobDevelopmentServicesID =empJobDevID,
PrevocServices = prevocServices,
PrevocServicesID =empPrevocID,
TransitionedPrevocToIntegrated =transitionedPrevocIntegrated,
EmploymentServiceMatchPref = empServiceMatchPref
};
context.tblEmploymentQuestionnaires.InsertOnSubmit(empPlan);
context.SubmitChanges();
}
}
I understand I can use more then 1 InsertOnSubmit(), See this question, I just don't understand how that would apply to my situation and the PK/FK creation.
The pk can be auto generated when the table's definition in the db does it for you. Also the property for the corresponding pk on the linq model has to configured to be updated after the insert, so it gets the auto generated ID.
I don't think the relation on those tables is on your linq model. Otherwise you should be able to do:
using (var context = MatrixDataContext.Create())
{
var empPlan = new tblEmploymentQuestionnaire
{
CommunityJob = communityJob,
InsertDate = DateTime.Now,
InsertUser = user,
JobDevelopmentServices = jobDevelopmentServices,
JobDevelopmentService = new tblEmploymentJobDevelopmetService(),
PrevocServices = prevocServices,
PrevocService = new tblEmploymentPrevocService(),
PrevocServicesID =empPrevocID,
TransitionedPrevocToIntegrated =transitionedPrevocIntegrated,
EmploymentServiceMatchPref = empServiceMatchPref
};
context.tblEmploymentQuestionnaires.InsertOnSubmit(empPlan);
context.SubmitChanges();
}
ps. not having the relation in the model is a design decision, so the above doesn't mean that's the only way to do it. The way you showed (with the extra SubmitChanges calls as in the other answer) is perfectly valid, just responds to a different design.
I think the issue is (if I understand it correctly) you are deferring the inserting, except you don't know it...
Since you're creating FKs but differing their insertion until the end, it doesn't know what to do, so when you try to create the main entry it's enforcing the FK constraints (which might not exist yet), thus failing. Try creating the FK entries and actually submitting the changes to the database before insert the main entry.
For example, say you have the following tables:
Child
Toy
ToyOwner
ToyOwner has FK constraints on Child and Toy. If the entries are missing in that table, you will not be able to insert an entry into ToyOwner. So you'd have to do something like the following:
Child myChild;
Toy myToy;
//Queue up the changes that are going to be submitted
InsertOnSubmit(myChild)
InsertOnSubmit(myToy)
//Submit the queue
SubmitChanges();
//Now that those FKs are filled, we can insert the main entry with those FK values
ToyOwner = new myToyOwner
myToyOwner.Child = myChild
myToyOwner.Toy = myToy
//And insert the new queue into the DB
InsertOnSubmit(myToyOwner)
SubmitChanges();