linq to sql one-one relationship C# - c#

It is necessary that after the creation of records in the table "Clients" took up ID. Later ID used to create a new entry in the "Clients_details".
var user = GetUsers();
var userdet = GetclientsDetails();
string hashedpass = getMd5Hash(UIPassword.Text);
var newreg = new Clients
{
login = UILogin.Text,
password = hashedpass,
subscribeid = Convert.ToInt32(UIId.Text)
};
user.InsertOnSubmit(newreg);
user.Context.SubmitChanges();
var details = new Clients_details
{
city = UICity.Text,
first_name = UIFirst_name.Text,
last_name = UIFamiliya.Text,
name = UIName.Text,
Clients = newreg
};
userdet.InsertOnSubmit(details);
userdet.Context.SubmitChanges();
After this code fails:
"An attempt was made to perform an operation Attach or Add in relation to an object that is not new, and possibly loaded from another DataContext. This operation is not supported."
How to properly create a record that does not appear a mistake? Thank you!
private static Table<Clients> GetUsers()
{
var dce = new BaseDBMLDataContext();
return dce.Clients;
}
private static Table<Clients_details> GetclientsDetails()
{
var dce = new BaseDBMLDataContext();
return dce.Clients_details;
}

Looks like userdet.Context and user.Context was built using a different dataContext and that needs to be created using the same dataContext rather than instantiating a new one.

I think you need to only call the SubmitChanges only once in the end, and also you need to make sure the user and userdet you are using share the same context

As the error clearly states, you're using different contexts (user and userdet) for each entity to add. You should have one DataContext and use that one to add the entities.

Yes looks like you're using two different instances of the same context:
user.Context.SubmitChanges();
userdet.Context.SubmitChanges();
A good approach to build up your entities should be something like :
//Create your client details entity
var details = new Clients_details
{
city = UICity.Text,
first_name = UIFirst_name.Text,
last_name = UIFamiliya.Text,
name = UIName.Text
};
//Create your client entity
var newreg = new Clients
{
login = UILogin.Text,
password = hashedpass,
subscribeid = Convert.ToInt32(UIId.Text),
//Assigning the details entity (FK) to the client
ClientDetails = details
};
//Saving both the client and its details
user.InsertOnSubmit(newreg);
user.Context.SubmitChanges();

Related

Stripe; how to get subscriptionId when creating a customer with a new subscription

I'm creating a new customer and adding them to a subscription in one call like so:
StripeConfiguration.SetApiKey(StripeData.ApiKey);
var customerService = new CustomerService();
var myCustomer = new CustomerCreateOptions
{
Email = stripeEmail,
Source = stripeToken,
Plan = StripeData.MonthlySubscriptionPlanId
};
Customer stripeCustomer = customerService.Create(myCustomer);
Then I used to be able to do this:
myLocalUser.StripeCustomerId = stripeCustomer.Id;
myLocalUser.StripeSubscriptionId = stripeCustomer.Subscriptions.Data[0]?.Id;
But now the API isn't returning the customer's subscriptions so the second line fails
I'm now having to call the API again with this ugly code to get the customer's subscriptionId:
if (stripeCustomer.Subscriptions != null)
{
user.StripeSubscriptionId = stripeCustomer.Subscriptions.Data[0]?.Id;
}
else
{
//get subscriptionId
var cust = customerService.Get(stripeCustomer.Id, new CustomerGetOptions
{
Expand = new System.Collections.Generic.List<string> { "subscriptions" }
});
if (cust.Subscriptions.Any())
{
stripeSubscriptionId = cust.Subscriptions.First().Id;
}
}
CustomerService.Create() doesn't have the same Expand parameter option that the Get() method does...
This is expected, as subscriptions are no longer included by default on a customer object unless you expand them since API version 2020-08-27.
Creating a customer with a source and plan is still possible (although not the recommended integration path anymore since you might run into problems with 3DS and tax rates), although since you are on a newer API version you won't get the subscriptions list back. If you can you should update to creating subscriptions via their own API.
If you however still want to use this old integration path, you can still get the subscriptions back in the customer create call, you just need to expand the subscriptions on creation:
var customerService = new CustomerService();
var myCustomer = new CustomerCreateOptions
{
Email = stripeEmail,
Source = stripeToken,
Plan = StripeData.MonthlySubscriptionPlanId
};
myCustomer.AddExpand("subscriptions");
Customer stripeCustomer = customerService.Create(myCustomer);

create a new record in service entity

I have seen example of creating Accounts Entity records, Contacts entity records through C#, i wanted to know how do we create a service record in CRM through C#(.net) code.
Eg: We already have "Plumbing service" record in service entity view. So i wanted to create a new record in service entity through C# code (early or late binding doesn't matter).
Can someone help me on this with code.
Quite some XML is required when creating this Services from code. Additionally, before you can create a Service you will need to create a ResourceSpec and a ConstraintBasedGroup.
First create a ConstraintBasedGroup:
var bu = context.BusinessUnitSet.First().ToEntityReference();
var cbg = new ConstraintBasedGroup
{
BusinessUnitId = bu,
Name = "CBG1",
Constraints = "<Constraints><Constraint><Expression><Body>false</Body><Parameters><Parameter name=\"resource\"/></Parameters></Expression></Constraint></Constraints>"
};
var cbgId = OrganizationService.Create(cbg);
Then create a ResourceSpec:
var resSpec = new ResourceSpec
{
BusinessUnitId = bu,
Name = "RS1",
RequiredCount = 1,
ObjectiveExpression = "<Expression><Body>udf\"Random\"(factory,resource,appointment,request,leftoffset,rightoffset)</Body><Parameters><Parameter name=\"factory\"/><Parameter name=\"resource\"/><Parameter name=\"appointment\"/><Parameter name=\"request\"/><Parameter name=\"leftoffset\"/><Parameter name=\"rightoffset\"/></Parameters><Properties EvaluationInterval=\"P0D\" evaluationcost=\"0\"/></Expression>",
GroupObjectId = cbgId
};
var resSpecId = OrganizationService.Create(resSpec);
And finally, you can create your Service:
var svc = new Service
{
Name = "Service1",
Granularity = "FREQ=MINUTELY;INTERVAL=15",
ResourceSpecId = new EntityReference(ResourceSpec.EntityLogicalName, resSpecId),
InitialStatusCode = new OptionSetValue(0),
Duration = 15
};
OrganizationService.Create(svc);
I would suggest you create similar things using the UI of CRM in case you are wondering about the specific formats of the XML you require. The XML I used in my examples is pretty much the default XML CRM generates.

Create ActivityParty in CRM without early bound Entities

As a requirement I cannot use the early bound context created with "CrmSvcUtil". The problem is that a new phonecall activity expects two fields ('from' and 'to') which are Entities of type activityparty. The standard XRM/CRM namespace does not contain a class similar to ActivityParty created with the Utility.
I tried filling it with an EntityCollection but then the field will be empty. Next I tried to recreate the structure of a working phonecall activity. EntityCollection "activityparty" -> with one Entity "activityparty" -> with EntityReference attribute "partyid" -> the entity ref (e.g. "contact" and the contact's id). But it simply does not work.
How can I create an ActivityParty (or better a phonecall Activity) with the "normal" Entitiy classes?
If I'm right you don't need to use an EntityCollection but an array of Entity
To create a phone call with late bound syntax will be:
Entity from1 = new Entity("activityparty");
Entity to1 = new Entity("activityparty");
Entity to2 = new Entity("activityparty"); // two contacts inside the to field
from1["partyid"]= new EntityReference("systemuser", userId);
to1["partyid"]= new EntityReference("contact", contact1Id);
to2["partyid"]= new EntityReference("contact", contact2Id);
Entity phonecall = new Entity("phonecall");
phonecall["from"] = new Entity[] { from1 };
phonecall["to"] = new Entity[] { to1, to2 };
// other phonecall fields
Guid phonecallId = service.Create(phonecall);
Even though I upvoted the answer but I had simmilar problem with serialization of ActivityParty. I came to solution that doesn't require you to give up on early bound entities.
what you need to do is something like this:
IEnumerable<ActivityParty> party = new [] { new ActivityParty { PartyId="", EntityLogicalName="..." } };
phonecall["to"] = new EntityCollection(party.Select(x => x.ToEntity<Entity>).ToList());
(I didn't test the code and wrote it from the air but you should feel the idea)
I vote for TrN because i was looking for any kind of example, and it's the only early bound example that i could find.
His example Actually helped me create an PhoneCall entity that had the Attribute "From" pointing to the Lead that actually made the call. I never fully understood the IEnumerable<ActivityParty> enumerator. Thanks to TrN i understand it enough to use it.
Here is my code regarding the PhoneCall activity that I've tested and it works. Everytime an existing Lead calls. The PhoneCall activity gets saved with the correct Attribute values linked to the correct Lead.
IEnumerable<ActivityParty> party = new[] { new ActivityParty { LogicalName = ActivityParty.EntityLogicalName , PartyId = eref2 } };
Console.WriteLine("Logging activity to {0}", firstName);
Console.WriteLine("... \n" );
PhoneCall newCall = new PhoneCall { Description = "Missed phone call from this lead", DirectionCode = true, RegardingObjectId = eref2,
Subject = "Missed Call", PhoneNumber = MissedCall, OwnerId = User, From = party };
Guid newCallId = service.Create(newCall);
Console.WriteLine("Log successfully created \n \n ");
As i said, For Kirschi this isnt the real solution given his requirement of not having any context. But anyone who wants/can use provided context and is curious how the IEnumerable<ActivityParty> works, this might help them to create a proper PhoneCall Activity.
Here is working code for the same. Feel free to reach out if anyone faces any issue.
private static void fetchRelatedPhoneCalls(IPluginExecutionContext context, IOrganizationService service, Guid yourGuid, Entity opp)
{
string strFetchPhoneCalls = string.Format(FetchQuery.bringFetchQueryForPhoneCalls(),yourGuid);
EntityCollection entPhoneCalls = (EntityCollection)service.RetrieveMultiple(new FetchExpression(strFetchPhoneCalls));
if (entPhoneCalls != null && entPhoneCalls.Entities.Count > 0)
{
for (int i = 0; i < entPhoneCalls.Entities.Count; i++)
{
Entity entPhoneCall = (Entity)entPhoneCalls.Entities[i];
string[] strAttributesPCtoRemove = new string[] { "createdon", "createdbyname", "createdby"
,"modifiedon", "modifiedby" ,"regardingobjectid","owninguser"
,"activityid", "instancetypecode", "activitytypecode" // PhoneCall Skip
};
Entity entNewPhoneCall = this.CloneRecordForEntity("phonecall", entPhoneCall, strAttributesPCtoRemove);
entNewPhoneCall["regardingobjectid"] = new EntityReference(context.PrimaryEntityName, context.PrimaryEntityId);
entNewPhoneCall["to"] = this.getActivityObject(entNewPhoneCall, "to");
entNewPhoneCall["from"] = this.getActivityObject(entNewPhoneCall, "from");
service.Create(entNewPhoneCall);
}
}
}
private static Entity CloneRecordForEntity(string targetEntityName, Entity sourceEntity, string[] strAttributestoRemove)
{
Entity clonedEntity = new Entity(targetEntityName);
AttributeCollection attributeKeys = sourceEntity.Attributes;
foreach (string key in attributeKeys.Keys)
{
if (Array.IndexOf(strAttributestoRemove, key) == -1)
{
if (!clonedEntity.Contains(key))
{
clonedEntity[key] = sourceEntity[key];
}
}
}
return clonedEntity;
}
private static EntityCollection getActivityObject(Entity entNewActivity, string activityFieldName)
{
Entity partyToFrom = new Entity("activityparty");
partyToFrom["partyid"] = ((EntityReference)((EntityCollection)entNewActivity[activityFieldName]).Entities[0].Attributes["partyid"]);
EntityCollection toFrom = new EntityCollection();
toFrom.Entities.Add(partyToFrom);
return toFrom;
}

Entity Framework: creating standalone entity

Good day, stackoverflow.
My question is: when the entity from DataContextModel is instantiated somewhere in the code, does it already have references to the database record? Or can it be used as common class ? For example:
public void SomeMethod()
{
var FirstEntity = new DBEntity(); //DBEntity is some entity from the database
var SecondEntity = new DBEntity();
var ThirdEntity = new DBEntity();
DbSet<DBEntity>.Add(SecondEntity);
DbSet<DBEntity>.Add(ThirdEntity);
DbContext.SaveChanges();
}
So, will FirstEntity be affected somehow, or it will be removed, when the SomeMethod exits?
Thanks in advance.
It's just a plain class if outside the context.
But be careful, suppose this FirstEntity is referenced inside another object, as in:
var FirstEntity = new DBEntity();
var SecondEntity = new DBEntity();
var ThirdEntity = new DBEntity();
DbSet<DBEntity>.Add(SecondEntity);
DbSet<DBEntity>.Add(ThirdEntity);
SecondEntity.Sibling = FirstEntity;
When you save changes, if Sibling in the example is a foreign key reference, it will automatically add FirstEntity to the database.
Another example to be clear:
var Computer = new ComputerEntity();
var Motherboard = new MotherboardEntity();
Computer.Motherboard = Motherboard;
DbSet<ComputerEntity>.Add(Computer);
DbContext.SaveChanges();
This will save both Computer and Motherboard to the DB.

Entity Framework: adding existing child POCO to new Parent POCO, creates new child in DB

Im wanting to use Entity Framework POCO in a disconnected (from context) mode. In my scenario I'm creating a new Parent object and want to attach an existing child object to it and then save it to the db.
The code below undesirably inserts a new Course record when saving a new Student record, when instead I want the existing Course record linked to the new Student record.
How can I do this in Entity Framework where...
the objects can be disconnected from the context. (i.e. Queried in one context and then saved in a different context)
I dont need to re-query the child record from the DB just so I can attach it to the parent when I'm saving to db. I really want to avoid doing extra trips to the db when I already have it as an object in memory.
This page shows a database diagram that the code below is based on http://entityframeworktutorial.net/EF4_EnvSetup.aspx#.UPMZ4m-UN9Y
class Program
{
static void Main(string[] args)
{
//get existing course from db as disconnected object
var course = Program.getCourse();
//create new student
var stud = new Student();
stud.StudentName = "bob";
//assign existing course to the student
stud.Courses.Add(course);
//save student to db
using (SchoolDBEntities ctx = new SchoolDBEntities())
{
ctx.Students.AddObject(stud);
ctx.SaveChanges();
}
}
static Course getCourse()
{
Course returnCourse = null;
using (var ctx = new SchoolDBEntities())
{
ctx.ContextOptions.LazyLoadingEnabled = false;
returnCourse = (from s in ctx.Courses
select s).SingleOrDefault();
}
return returnCourse;
}
}
I believe there are few ways of accomplishing this.
You can specify that course entity is unchanged rather than added, along these lines:
ctx.Entry(course).State = EntityState.Unchanged;
Or instruct your context, that you are working with existing entity:
ctx.Courses.Attach(course);
More info here:
http://msdn.microsoft.com/en-us/data/jj592676.aspx
EDIT
There are some running samples from my solution, I verified they work as expected.
In all cases we have Publisher record in database with ID = 2 and Name = "Addison Wesley" (irrelevant to the example, but just for good measure).
Approach 1 - Setting Entity State
using (var context = new Context())
{
var book = new Book();
book.Name = "Service Design Patterns";
book.Publisher = new Publisher() {Id = 2 }; // Only ID is required
context.Entry(book.Publisher).State = EntityState.Unchanged;
context.Books.Add(book);
context.SaveChanges();
}
Approach 2 - Using Attach method
using (var context = new Context())
{
var book = new Book();
book.Name = "Service Design Patterns";
book.Publisher = new Publisher() { Id = 2 }; // Only ID is required
context.Publishers.Attach(book.Publisher);
context.Books.Add(book);
context.SaveChanges();
}
Approach 3 - Setting Foreign Key value
using (var context = new Context())
{
var book = new Book();
book.Name = "Service Design Patterns";
book.PublisherId = 2;
context.Books.Add(book);
context.SaveChanges();
}
For this last approach to work I needed to add extra property PublisherId, it has to be named according to NavigationPropertyName + 'Id" convention to be picked up by EF auotmatically:
public int PublisherId { get; set; }
public Publisher Publisher { get; set; }
I am using here EF5 Code First, but it is very similar to POCO.
Entity Framework does not allow relationships that cross contexts.
If you place the reading of the course and connecting the course to the student within the same using statement, it would work.
I also tried the second option it worked for me. I did like the parent->child relationship happening at an object level first and save to db. Maybe I should just remove all the relationships between the entities that EF generates and manually control this myself.

Categories