I have been working with C# using a repository design pattern with Entity Framework (EF) that allows me to interact with the database using a generic class for each table.
This repository has all the functions that I would need such as: Adding a new entity into the database, updating an existing entity, deleting an entity, saving the context and so on...
Take, for example, I have an entity called 'Person' in the database. I would create a new class called PersonRepository which had all the functions I would need to change/add a value to the database.
As a result, to interact with the database, you create an instance of the repository class. This then allows you to call the functions of this class which in turn interacts with the database. The idea of this pattern is that all your database calls for an entity are isolated into a single class, this improves testability and separation of concerns.
I am learning how to use Core Data in my Swift programs and it appears to be similar to that of EF in C#. I have created the entities in the .xcdatamodel file and created the associated Cocoa Touch class via the Editor > Create NSManageedObject subclasses option.
I used the 'Category/Extension' CodeGen option, so, I then created a new class called 'Exercise'. From what I have read, this class can contain additional logic such as overriding the prepareForDeletion method. Does this mean I can add the addEntity, updateEntity functions onto this method and then call them from other code files?
My questions are:
Can I implement the same repository pattern that I can use in C#?
I believe this would be on the generated class of my entity (see image below)
Where do I place all my database call functions? If I can use this repository pattern I will place them on there, however, if I cannot, do I place them in a separate code file? Should I place them on the generated entity file which is created for the purposes of adding additional logic?
If I can use the repository pattern, is there a way to get the context injected into this class, or, do I have to call a getContext method each time I want to change it? In C# we can use the services to inject the context into the class each time I want to make changes to the database - I am unsure if the same is possible in Swift.
If I understand correctly, in Swift the equivalent of your 'repository' class could be one of two things. It could be context of core data, which you'd run queries and saves to OR (more likely) you would create a new class or struct that obscured away core data from the business side. Assuming the later, your "dataManager" class would perform all interactions with core data. It could then either return NSmanagedobjects to the business side, or you could map/transform/convert to some other type.
Yes, Exercise is a object that subclasses nsmanagedobject, so it has all the core data features of a managed object, but you can add any custom functions your want.
Your data manager class would perform the queries and return the correct objects. For example data manger.getExercises() -> [Exercises], dataManager.save(_ exercise: Exercise), etc....
You'll need to consider thread safety in your pattern. One option is converting your nsmanagedobjects to struct in your datamanager and not returning nsmangedobjects. Structs are thread safe and using codable you can easily convert between exerciseManagedOjbect and exerciseStruct. Plus, with this dataManager class example, you could remove core data for another persistence option in the future with reduced impact to your app overall.
Related
I'm getting into Core Data and have started making "Classes" out of entities. Do I use these classes based off of entities as regular classes with methods etc?
Normally if I was using SQL directly I would have classes for each of my database objects (Tables) that store the working data and perform their functions.
Is this the same with Core Data - do I use the entity-based classes (subclasses of NSManagedObject).
So I might have these entities: Business -> Departments -> Employees
To comply with Core Data - do I make one class for each of these subclassing NSManagedObject and then add methods to it accordingly (like I would an NSObject class)?
Yes, you usually use the Core Data generated classes. You usually don't add methods to those classes, instead you should put them into a Category. This is because if you change an entity, you need to regenerate the class which will erase any methods that you added.
Yes(ish). They are your model classes. You aren't creating them 'out of' entities, they are the code representation of your entities.
You should have one class per entity, but you shouldn't create them yourself. You should get Xcode to create the classes. Or, better yet, use mogenerator.
Its more of a best practices sort of question. Here it goes...
I have automatically generated some classes for my entities in core data , now I want to use them as model objects to convert those models in JSON and send it over to the server. So my question is whether it is ok to use these classes or should I create separate classes and use a data mapper class to map these core data and model classes...
Which is a better approach and why...?
Thanks for your inputs...
You can use your NSManagedObject subclasses and add methods to those classes as you would any other NSObject class. This is perfectly acceptable (and would be better practice than to create separate object classes and using data mappers).
Use mogen to avoid the problem mentioned by #svena. It will automatically manage generation of core data models to prevent overriding your own code. Also I would suggest trying RestKit for server interactions. At least you can borrow their object serialization code because it does exactly what you want.
I have a class library with objects defined that I will use in an application. In a seperate class library I have my Entity Framework object model, where I add a function import, select my stored procedure, and generate a complex type. Rather than generate a complex type, is there any way to point it to the object I defined in my other class library? Essentially, I want my objects all in a seperate library than my data access layer. Do I need to write my own mapping logic?
Note, this is my first EF attempts. I guess you could say I am using a code first approach. I am building the objects (POCO) I want to use and they are in their own class library (My object model). In a seperate class library I am using EF and exposing methods that accept or return classes in my object model, that can be called by my appliation (data access layer).
In my database I have a set of stored procedures. Stored procedures are the only way my data access layer can interact with the database.
In my data access layer, I have created an edmx file, and add function imports to the edmx file. The edmx entity container access is set to internal, so it isn't exposed outside of the class library. Instead, I have a public class with public methods that can be called by my application. Those methods make calles to the object context class to fire the storedproceds, and return objects from my object model. The purpose here is that I am only using the entity framework to handle stored procedure calls. In essence the data access technology is completely hidden from the application. The application only knows how to call specific functions exposed from my data access library, and deal with objects exposed in my object model. Obviously I could write code that translates complex types defined in the edmx to types in my object model, but I'm just wondering if there is any way to avoid writing that code myself, and just have EF use my object model instead of its complex types...
I've tried to use Entity Framework 4 and POCO for my MVC 3 project. May be, I don't understand the main idea of this ORM, but the problem is following:
I added ADO .NET Entity Data Model and make model according to database.
I clicked Add Code Generation Item and added ADO .NET POCO Entity Generator.
It makes classes for every database table.
I want to add some methods to work with data (Add, Update, Delete, GetAll etc) to appropriate models.
For LINQTOSQL I added partial classes and placed them to Models. But now I can't do it because:
a) Models folder has classes with the same names, which was created by POCO.
b) If I place my partial class in the another folder, it will be another namespace - so, such classes won't be partial one.
c) If I place my code in POCO classes, it can be destroyed during update POCO.
How can I use it? Where sould I place my methods for data working?
Is the best way to make for POCO and EF the other project - http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx?
First of all you don't have to write your CRUD inside POCO,
There are many places where you can do it like in edmx.cs file or write one more layer which is called as CRUD Services which handles the Database operations using context object.
Now coming to your questions,
Create separate Models folder and place the Model classes in there.
Your Model class may like this,
EmployeeDepartmentModel
{
prop EmpList List(Emp);
prop DeptList List(Dept);
//Emp and Dept are my POCOs
}
So now I have to fill both of these list(Your CRUD question),
For that, I will Create one method in Controller class(its better to write such logic in some another library, but for time being I suggest you to create in Controller),
FillTheModel()
{
EmployeeDepartmentModel.EmpList = EDMX.GetAllEmployees;
EmployeeDepartmentModel.DeptList = EDMX.GetAllDepartments;
}
Now you can bind this model with your view.
You can place the partial classes in another folder and modify the namespace.
I agree with allisewell, but if you really want to add parts to partial classes, give files another name,
e.g. MyPoco.Part2.cs or modify t4 template to name generated files
e.g. Poco.Generated.cs
I want to create an integration test which grabs an EF entity from the DB, clones it to a detached object, modifies it and then saves it back and compares it again to the original.
However, I was using AutoMapper to create the clone of the class, but it turns out this is also tracked or an alias to the original object. I need it to be completely detached from EF, and am able to do this outside of my repository class (i.e. not using any EF detach methods).
The reason for doing this is my EF class contains nested collections of other classes and EF doesn't handle persisting the whole object tree. Hence, my Update() method in my repository class handles this and I want my NUnit test to test this code. I want the test is to be able to quickly create a copy of my original class without EF tracking it.
Creating a cloned object containing current, original, or database
values The DbPropertyValues object returned from CurrentValues,
OriginalValues, or GetDatabaseValues can be used to create a clone of
the entity. This clone will contain the property values from the
DbPropertyValues object used to create it. For example:
using (var context = new UnicornsContext())
{
var unicorn = context.Unicorns.Find(1);
var clonedUnicorn = context.Entry(unicorn).GetDatabaseValues().ToObject();
}
Note that the object returned is not the entity and is not being
tracked by the context. The returned object also does not have any
relationships set to other objects.
The cloned object can be useful for resolving issues related to
concurrent updates to the database, especially where a UI that
involves data binding to objects of a certain type is being used. (See
Part 9 for more details on dealing with optimistic concurrency.)
*From http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property-values.aspx
Hope it can helps others
All troubles are gone once you're using EF 5+ where they introduced AsNoTracking() method.
The line below returns an unlinked instance, so all the context won't be aware about any changes in that instance:
context.Clients.AsNoTracking().FirstOrDefault(item => item.Id == id);
If Clients has a reference to Address and you want an unlinked instance of it too, just use an Include:
context.Clients
.Include("Address").AsNoTracking()
.FirstOrDefault(item => item.Id == id);
If it is a test you can do anything and you don't have to be binded to any architectural approach like repository. Your repository probably receive context as injection so you can have access to it. Another point is that I don't believe that AutoMapper will create tracked entity.
The one way to make a copy of the class is using serialization which by default saves only public fields (Xml serialization or DataContract serialization). Serialize the object and deserialize it back to a new instance. Serialization will save the whole object graph and deserialized object graph will be detached. Just be aware that that those serializations don't likes cyclic references in object graph (navigation property from A to B and from B to A from cycles). Serialization is also too much aggresive so it can traverse the graph more deeply then you want - this can be especially dangerous in many to many relations.
The best approach is using either ICloneable interface and implement Clone or define support methods which will do different clones with required depth.
Here is another approach for clonning EntityObject based entities. It is tough code, especially part with Reflection.Emit. But this will not help you because code-first is using POCOs.