Background: Project is a Data Import utility for importing data from tsv files into a EF5 DB through DbContext.
Problem: I need to do a lookup for ForeignKeys while doing the import. I have a way to do that but the retrieval if the ID is not functioning.
So I have a TSV file example will be
Code Name MyFKTableId
codevalue namevalue select * from MyFKTable where Code = 'SE'
So when I process the file and Find a '...Id' column I know I need to do a lookup to find the FK The '...' is always the entity type so this is super simple. The problem I have is that I don't have access to the properties of the results of foundEntity
string childEntity = column.Substring(0, column.Length - 2);
DbEntityEntry recordType = myContext.Entry(childEntity.GetEntityOfReflectedType());
DbSqlQuery foundEntity = myContext.Set(recordType.Entity.GetType()).SqlQuery(dr[column])
Any suggestion would be appreciated. I need to keep this generic so we can't use known type casting. The Id Property accessible from IBaseEntity so I can cast that, but all other entity types must be not be fixed
Note: The SQL in the MyFKTableId value is not a requirement. If there is a better option allowing to get away from SqlQuery() I would be open to suggestions.
SOLVED:
Ok What I did was create a Class called IdClass that only has a Guid Property for Id. Modified my sql to only return the Id. Then implemented the SqlQuery(sql) call on the Database rather than the Set([Type]).SqlQuery(sql) like so.
IdClass x = ImportFactory.AuthoringContext.Database.SqlQuery<IdClass>(sql).FirstOrDefault();
SOLVED:
Ok What I did was create a Class called IdClass that only has a Guid Property for Id. Modified my sql to only return the Id. Then implemented the SqlQuery(sql) call on the Database rather than the Set([Type]).SqlQuery(sql) like so.
IdClass x = ImportFactory.AuthoringContext.Database.SqlQuery<IdClass>(sql).FirstOrDefault();
Related
What is a good way to avoid duplication of a class instance when it is created using the __init__() function.
This question is a result of this issue.
Context (using employee class example):
Lets say I have an employee class: __init__(self,name,dept)
I also have a method, employee.info(self) that prints out name and dept of any employee.
However a user could just add an employee by calling a=employee(args..). They could do it multiple times using the same instance variable a, but different employee names.
This will cause issues if they try to print a.info(), as each time a different employee name will be printed.
Is there a better way to do this? I know it is possible to have the __init__() "pass" and define a new method to create an instance.
Expect results:
>>Adam=employee('marketing')
>>Adam.info()
>>Adam works in marketing.
OR
>>a=employee('Adam','marketing')
>>a=employee('Mary','marketing')
>>Error: employee instance with identifier "a" already exists.
>>Use employee.update() method to modify existing record.
Is there a cleaner way of doing it? (as you might guess, I am still learning python).
Or is it good practice to write an explicit function (instead of a class method) to add new employees?
what you try is impossible, because in
a=employee('Adam','marketing')
a is not an object but a variable that points to the object employee('Adam','marketing').
When you do
a=employee('Mary','marketing')
you say to python that now, a must now not point to the object employee('Adam','marketing') but to the object employee('Mary','marketing'). And then, if you have no more variable to reference the object employee('Adam','marketing'), the garbage collector will destroy it.
You must consider that in python all is object, but not the variables that are only references to manipulate objects.
I have been racking my brains over the same problem and have finally managed to figure out a workaround :
Create a dictionary that stores the employee name and the related object like this :
total_emp_dict = {}
Add this inside the def __init__ of the class employee : total_emp_dict[name] = self. This will ensure to add each employee name as key and the object associated will be added as value.
Now create a new function outside & before the employee class is defined, let's call it create_new_emp. It will go like this :
#function to check and avoid duplicate assignment of instances
def create_new_emp(name, dept):
if name in total_emp_dict:
return total_emp_dict[name]
else:
return employee(name, dept)
When creating a any new employee, use this new function : a = create_new_emp("Adam", HR) instead of a = employee("Adam", HR)
Explanation : This function will ensure that duplicate assignment is not done. If "a" is already assigned to "Adam", this function will return object of "Adam" to "a", when called again. But if nothing is assigned to "a", then this function will handover to the attributes (name, dept) to employee class and create a new instance. This instance will then be assigned to "a".
I don't know if this is the best solution for this problem, but honestly this is the only solution I have found so far and it works great for me without much fuss / extra code space. Hope it works for you too! :)
I have the following model:
User
...
Group
...
Sharing
objectId (Either UserId GroupId)
In Sharing entity I want to store either UserId or GroupId and differentiate between them. Simply using Either doesn't work:
Not in scope: type constructor or class `UserId'
Not in scope: type constructor or class `GroupId'
Adding a new sum-type also doesn't work:
data SharingIdType = SharingUserId UserId | SharingGroupId GroupId
Not in scope: type constructor or class `SharingIdType'
Moving SharingIdType into another module isn't possible, because it uses UserId and GroupId types. The only way I see is to create an entity for each sharing type, like UserSharing/GroupSharing.
Other than that, how to approach this problem?
After searching for some time and thinking about it I concluded there are two possible solutions:
1.
If number of SharingIdTypes is static or rarely changes (means, it is OK to recompile the source to change it or alter the DB schema), the proper way to handle the problem is to have to entities for each sharing type:
User
...
Group
...
UserSharing
userId UserId
GroupSharing
groupId GroupId
Here the "sumness" of the problem is moved to DB queries. Whenever I need to find out with what something shared, I make two selectLists and query two tables instead of one.
2.
If number of SharingIdTypes needs to be altered dynamically, the SharingType entity is needed:
User
...
Group
...
SharingType
description String
Sharing
objectId SharingTypeId
This table is filled up with values corresponding to SharingIdTypes constructors:
do
insert $ SharingType "user"
insert $ SharingType "group"
Now whenever we share something, we refer SharingTypeId.
Do you know is there any like a global reference book of MS CRM entities in the system?
I need to resolve entity id to the entity type without checking every single entity for presence of given GUID.
Is it possible?
I don't know of any supported way, but I believe you could to a SQL query on the PrincipalObjectAccess table in the database and retrieve the value of ObjectTypeCode where ObjectId is the GUID.
For annotation you need to look at the field objecttypecode to determine the entity type of objectid.
You can either generate a list of entity logical names and object type codes in your code as a Dictionary object (this will give you the fastest performance but requires you know all the entity types that will be in the system at the time you compile) or (if you are on CRM 2011 UR12+ or CRM 2013) you can do a MetadataQuery.
You can read more about doing a metadata query here: http://bingsoft.wordpress.com/2013/01/11/crm-2011-metadata-query-enhancements/
Sample code for your requirement:
var objTypeCode = [INTEGER] //Make this this the annotation.objecttypecode
MetadataFilterExpression entityFilter = new MetadataFilterExpression(LogicalOperator.And);
EntityFilter.Conditions.Add(new MetadataConditionExpression("ObjectTypeCode", MetadataConditionOperator.Equals, objTypeCode);
EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
{
Criteria = entityFilter
};
RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = new RetrieveMetadataChangesRequest()
{
Query = entityQueryExpression,
ClientVersionStamp = null
};
RetrieveMetadataChangesResponse response = (RetrieveMetadataChangesResponse)orgService.Execute(retrieveMetadataChangesRequest);
You can reduce the metadata retrieved, for better performance, as shown here: How to get the CRM Entity Name from the Object Type Code of a RegardingID?
I have a type called "Comment" that I'm saving to Azure Table Storage. Since a comment can be about any number of other types, I created an interface which all of these types implement, and then put a property of type ICommentable on the comment. So Comment has a property called About of type ICommentable.
When I try to save a Comment to Azure Table Storage, if the Comment.About property has a value, I get the worthless invalid input error. However, if there is no value for Comment.About, I have no problem. Why would this be?
Comment.About is not the only property that is a reference type. For example, Comment.From is a reference type, but the Comment.About is the only property of a type that is an interface.
Fails:
var comment = new Comment();
comment.CommentText = "It fails!";
comment.PartitionKey = "TEST";
comment.RowKey = "TEST123";
comment.About = sow1;
comment.From = person1;
Works:
var comment = new Comment();
comment.CommentText = "It works!";
comment.PartitionKey = "TEST";
comment.RowKey = "TEST123";
//comment.About = sow1;
comment.From = person1;
Thanks!
Windows Azure table storage can store only a handful of types, none of which are the ICommentable type you created: http://msdn.microsoft.com/en-us/library/windowsazure/dd179338.aspx.
The Azure Table Storage Client does not support granular means of controlling which properties are persistable.
You may wish to check out my open source project on CodePlex which allows fine grain control over which fields/properties to persist to table storage and how to serialize them. (http://lucifurestash.codeplex.com/)
Edit: Fixed typo + clarifications.
Say I have a stored procedure that returns dataSet from 2 different tables. Example:
SELECT Customers.FirstName, Customers.LastName, SUM(Sales.SaleAmount) AS SalesPerCustomer
FROM Customers LEFT JOIN Sales
ON Customers.CustomerID = Sales.CustomerID
GROUP BY Customers.FirstName, Customers.LastName
Is there any way to get a strongly typed list as a result from this stored procedure ? Something like this:
StoredProcedure sp = myDevDB.GetCustomerSales();
List<MyCustomType> resultSet = sp.ExecuteTypedList<MyCustomType>();
How and where do I define the MyCustomType class ? How do I map its properties to the actual table columns ?
thanks,mehul
I solved it by creating a class (in the same place as all my other classes, but I didn't extend IActiveRecord, it's just a vanilla class).
Make sure the property names have exactly the same name and data type as the ones in the procedure, then call db.sproc(params).ExecuteTypedList().AsQueryable(); and it populated fine.