Introduction to Object-Relational Mapping for DBAs – Part 3

Why Developers Use ORMs (i.e. their Strengths)

This is the third and final part of a lighting talk I’m giving at the SQL Saturday Edmonton Speaker Idol Contest.   Imagine I’m actually speaking the words below and showing some of the images on slides and/or doing a demo.

If you don’t want to read Part 1 or Part 2 the basically give an example of a developer using ORM, panic over indexes, and then show more ORM examples.  I don’t think it will all fit in a 15 minute talk.

This is a rough draft so constructive feedback at chris.cumming@saturdaymp.com is much appreciated.

The first obvious reason developers use a ORM is it lets them create an application knowing little to no SQL.  A developer without SQL training can use the ORM to help them generate the database and write queries for them.  The DDL and SQL queries created by the ORM is probably just as good or better then what a novice SQL developer could write.

ORMs also write a lot of the repetitive SQL for the developer.  You know, the SQL for find a certain piece of data like a user or inventory item.  The SQL to update that piece of data or create it if it does not exist.  The boring repetitive CRUD SQL statements.  Without an ORM developers used to have write ADO.NET code which looked like:

using (SqlConnection conn = new SqlConnection(connString))
{
  // Query to load all the information about a customer.
  // province.  Hopefully there are no typos in the SQL.
  // Use parameters so we don't have
  // SQL injection issues.
  var cmd = new SqlCommand("
    Select c.*, a.*, p.Abbreviation
    From Customers c 
    Inner Join on Addresses a
    Inner Join on Provinces p
    Where c.Id = @CustomerId"
    And a.AddressType = @HomeAddressType
  ); 
  cmd.Parameters.AddWithValue("@CustomerId", customerId);
  cmd.Parameters.AddWithValue("@HomeAddressType", HOME_ADDRESS_TYPE);

  // The adapter to read the data from the database.
  var dataAdapater = new SqlDataAdapter(cmd, conn);
  
  // The dataset to fill with data.
  // I think in .NET Core 2 you can create a DataTable
  // instead of always using a DataSet.  If true that would
  // have been great 20 years ago.
  var dataSet = new DataSet();
  dataSet.Tables.Add();

  // Read the data and fill the dataset.
  dataAdapter.Fill(dataset.Tables[0]);
} // Connection to database is closed.

// Show the data in the type unsafe dataset. Hope 
// you don't have a typo in the column names and 
// you correctly handle database nulls (not shown). 
Console.WriteLine{$"Name: {drow["Name"]} 
  Street: {drow["StreetAddress"]} 
  City: {drow["City"]} 
  Province: {drow["Abbreviation"]});

Actually, I’ll tell you DBAs a secret.  Back in the ADO.NET days no developer ever wrote all the code in the first example.  Instead we usually created our own custom code library that handled all the work to fill a DataSet with data.  The problem is every development shop had it’s own custom data access library with their own features and/or bugs.  But still, it was ugly code to write and would often break if the underlying database changed even a bit.

Using Entity Framework, Microsoft’s ORM, the above code looks like:

using (var ctx = new MyDbContext)
{
  // No need to worry about typos.  If Customers
  // is misspelled then a compile error will occur.
  // Also no need to worry about SQL injection.
  var customerToView = ctx.Customers
    .Include(customer => customer.Address)
    .ThenInclude(address => address.Province)
    .Where(customer => customer.Id.Equals("Id"))
    .ToList();
} // Connection to database is closed.

Console.WriteLine($"Name: {customerToView.Name} 
  Street: {customerToView.Address.StreetAddress} 
  City: {customerToView.Address.City} 
  Province: {customerToView.Address.Province.Abbreviation}); 

Wow, that is a lot less code and much easier to read.  The developer still needs to understand a bit of the underlying database structure but a lot of the grunt work is taken care of.

Finally the biggest strength of a ORM is abstraction of data access.  It lets developers focus on the business logic and GUI of the application.  Data access is this magic thing that just happens.

Actually that’s not 100% true.  Like all abstractions ORMs leak so the developer has to know something about the underlying database but for those brief few moments the developer has one less thing to think about.  As Sherlock Holmes put it so eloquently said about developers:

“I consider that a man’s developer’s brain originally is like a little empty attic, and you have to stock it with such furniture as you choose. A fool takes in all the lumber of every sort that he comes across, so that the knowledge which might be useful to him gets crowded out, or at best is jumbled up with a lot of other things, so that he has a difficulty in laying his hands upon it. Now the skillful workman developer is very careful indeed as to what he takes into his brain-attic. He will have nothing but the tools which may help him in doing his work, but of these he has a large assortment, and all in the most perfect order. It is a mistake to think that this little room has elastic walls and can distend to any extent. Depend upon it, there comes a time when for any addition of knowledge, you forget something, that you knew before. It is of the highest importance, therefore, not to have useless facts elbowing out the useful ones.”

“But the Solar System Database!” [Watson] I protested.

“What the deuce is it to me?” he interrupted impatiently:  “you say that we go around the sun store data in a database.   If we went round the moon stored the data on a stone tablet it would not make a pennyworth of difference to me or to my work”.

Good developers are good at using abstractions.  They create abstractions in code through functions, classes. and layers such as the GUI layer, business layer, etc.  An abstraction lets them to temporarily “forget” about the rest of the application and focus on the part they are working on.

Why DBAs Dislike ORMs (i.e. their Weaknesses)

Not only do good developers lover abstractions but they also understand their weaknesses.  Bad developers don’t understand that abstractions can have weaknesses.  Remember Uncle Ben’s famous words:

With great power abstractions comes great responsibility.

The most common mistake beginner ORM developers make is too turn on lazy loading and then do a loop.  The famous n+1 select problem.

using (var ctx = new MyDbContext)
  // Load all the customers
  // Select * From Customers;
  customers = ctx.Customers.ToList();

  // Print each customers city.
  foreach (var customer in customers)
  {
    Console.Writeline(customer.Name);

    // Select * From Addresses where CustomerId = ?
    Console.Writeline(customer.Address.City);
  }
}

The above code will send one query to get all the customers then send a separate query to get the address information.  If would look like:

Select * From Customers;

Select * From Address Where CustomerId = 1
Select * From Address Where CustomerId = 2
Select * From Address Where CustomerId = 3
Select * From Address Where CustomerId = 4
Select * From Address Where CustomerId = 5
...

This works great in test when there are only a couple of records but grinds to a halt in production.  Any DBAs seen something similar?

Bad, or I guess naive is better word, developers like lazy loading because the data just “magically” appears.  Good developers turn off lazy loading and write their code to only send one query.

using (var ctx = new MyDbContext)
{
  // Get all the customers and their addresses
  // in one query.
  // Select * From Customers c
  // Inner Join Addresses a On c.Id = a.CustomerId
  var customers = ctx.Customers
    .Include(customer => customer.Address)
    .ToList();
}

// Print each customers city.
foreach (var customer in customers) {
  Console.Writeline(customer.Name);

  // No query, data is already in memory.
  Console.Writeline(customer.Address.City);
}

Another common mistake when using ORMs is pulling back unnecessary data.  In the above example we only want the customer name and city but the generated query pulls back all the customer and address columns.  ORMs are great when you need all or most of the columns in a table but are not as useful when you only need one or two columns.

We can re-write the above to only bring back the columns we are interested in:

using (var ctx = new MyDbContext)
{
  // Get all the customers and their addresses
  // in one query.
  // Select c.Name, a.City From Customers c
  // Inner Join Addresses a On c.Id = a.CustomerId
  var customerCities = ctx.Customers
    .Include(customer => customer.Address)
    .Select(c => c.Name, c.Address.City)
    .ToList();
}

// Print each customers city.  Notice the
// data is flattened.
foreach (var custCity in customerCities ) {
 Console.Writeline(customer.Name);
 Console.Writeline(custCity.City);
}

Another big weakness of ORMs is complex queries.  ORMs really don’t handle joining lots of tables together or trying to have a complicated where and/or grouping.  These are best handled by writing SQL.  Needless to say reports should never use an ORM.  Instead use SQL or better yet a tool that helps you create reports.

The final weakness of ORMs is they don’t work well with stored procedures and views.  This can really be a problem is you are a DBA that likes all data access to go through views or stored procedures.  ORMs can also be a problem if you us a lot functions but that is usually less of an issue.

It’s not that ORMs can’t handle views or stored procedures it’s just not their strength.  The ORM abstraction works best if tables can be mapped to classes and fields to properties.  I once saw a project that used an ORM but had to access all the data via stored procedures and it was not pretty.  It was like the data access code fell from the top of the ugly tree and hit every branch on the way down.

How DBAs and ORMs can Work Together

I recently heard a good quote from the Supergirl TV show which I think is appropriate:

GIF Team Work Makes the Dream Work

The quote probably didn’t originate from Supergirl but you get the idea.  Good teams have empathy for each other and hopefully this talk has increased your empathy for developers by showing you why they use ORMs.

Hopefully developers have empathy for you as well.  A good developer respects that the DBA is the guardian of the data.  It’s your job to make sure the data is accurate and readily available.  Developers often focus on how their application uses the data and forgets other applications might have different data access requirements.

Assuming you are working with a good developer keep the following in mind:

  1. Let the ORM generate schema changes but make sure to review them.  The developer might not realize that renaming the column caused the column to be dropped and recreated resulting in data loss.
  2. Let the ORM access the tables directly.  Only force access threw a  view or stored procedure if there is a good reason.
  3. Don’t be afraid to adapt the ORM’s naming schema.  An ORM will often assume things like ID is the primary key column, table names are plural, foreign keys are <tablename>ID, etc.  If you can’t adopt the ORM’s preferred naming scheme then at least be consistent in your naming.
  4. Don’t worry about being made redundant.  ORMs can do some of the work DBAs used to do but not all of it and as we pointed out above ORM generated SQL should still be reviewed.  Also ORMs can’t do the A part of DBA (i.e. they don’t backup your database, secure it, create RAID arrays, etc).
  5. If you work with bad developers try to educate them.  They might just be naive.  If you can’t educate the developers and management won’t help you don’t be afraid to move on.  Life is too short to…<fill in the blank>.

Remember “Teamwork makes the dream work”.

Now that all three parts are written it looks longer then 15 minutes.  To find out what gets cut, changed, and added you will need to attend the  SQL Saturday Edmonton Speaker Idol Contest.  Or just wait till I post the slides online.

As I said above, this is a rough draft so constructive feedback at chris.cumming@saturdaymp.com is much appreciated.  Thank you.

Posted in Code Examples, Software Development | Tagged , , | Comments Off on Introduction to Object-Relational Mapping for DBAs – Part 3

Introduction to Object-Relational Mapping for DBAs – Part 2

This is part two of a lighting talk I’m giving at the SQL Saturday Edmonton Speaker Idol Contest.   Imagine I’m actually speaking the words below and showing some of the images on slides and/or doing a demo.  Code can be found here.

If you don’t want to read Part 1 it basically started the ORM example and ended in a panic over indexes.  

This is a rough draft so constructive feedback at chris.cumming@saturdaymp.com is much appreciated.

Now that we have our initial panic out of our system lets get back to Bud.  The next thing he wants to do is link a logged in user to a player.  A player needs to have a name and be linked to the login.  Bud creates a model, really just a simple C# class, and puts in all the information he wants to store a player.

Player Model

Looks kind of like a database table.  The one question you might have is what is a ApplicationUser?  It turns out a ApplicationUser is another model in the project that was auto-created when we choose to have authentication in our application.  It’s the logged in user.

If we open that ApplicationUser class we see it does not define any fields.  It doesn’t define any fields in the child class but the parent class does.  I’m not going to explain inheritance here but rest assured the fields are defined as shown below.

Empty Application User Model

Application Model Parent With Fields

Because the relationship is one-to-one Bud does add a new property to the ApplicationUser model.

Application User Model Linked To Player

Now the application knows that ApplicationUser has a one-to-one relationship to Player.  One other thing Bud has to do is add his new class the DB context.  Entity Framework might find his new model but it’s best if it’s listed.

Player Model Added to DB Context

Now Bud can create a new migration for his new Player model.

Add-Migration CreatePlayerTable

 

Add Player Table Migration

This creates the <timestamp>_CreatePlayerTable file.  If we open it up we see it creates the Player table and also a foreign key relationship to the ApplicationUser which maps to the AspNetUsers table.

Player Migration Create Table

Player Migration Foreign Key To Application User

Now that the migration file is created Bud runs the migration to add the Players table to his database.

Update-Database

 

Update Database Add Player Table

Now if we look in the database we find the new Players table, notice it’s plural, and it has a foreign key to the AspNetUsers table.

Players Table In SQL Server

OK, enough of following Bud, we are running out of lightning time.  Lets talk about why Bud would want to use an ORM tool such as Entity Framework.

You can find part 1 here. and part 3 here.  You can find the code for this talk here.  As I said above, this is a rough draft so constructive feedback at chris.cumming@saturdaymp.com is much appreciated.

 

Posted in Code Examples, Software Development | Tagged , , , , | Comments Off on Introduction to Object-Relational Mapping for DBAs – Part 2

Introduction to Object-Relational Mapping for DBAs – Part 1

This is the part one of a lighting talk I’m giving at the SQL Saturday Edmonton Speaker Idol Contest.   Imagine I’m actually speaking the words below and showing some of the images on slides and/or doing a demo.  Code can be found here.

This is a rough draft so constructive feedback at chris.cumming@saturdaymp.com is much appreciated.

Skip ahead to Part 2 if don’t feel like reading all of part 1.

Developer Bud wants to create a new application to track the board games he and his friends play.  He wants a simple website where him and his buddies can login to update the results from the board games they have played.  Being a .NET Developer he creates a ASP.NET MVC Core application with individual authentication.

Creating New ASP .NET MVC

Creating New ASP .NET MVC Authentication

By default this new application uses Entity Framework which is a object-relational mapping (ORM) framework.  Since he picked to use authentication the default ASP.NET application has a migration file that defines the authentication tables.

Authentication Migration File Location

Authentication Migration File

Even if you don’t understand C# you can probably see the above is describing a database but is not the usual SQL DDL.  We will return to this file later, for now lets continue to follow Bud.

Next he compiles and runs the application to make sure it works.  It loads up and looks like the below.

App Running For First Time

Everything looks good but when he tries to create a new user he gets the following error:

Trying To Register

Apply Migrations Registration Error

 

Following the advice he runs the migration.  Actually before he runs the migration he changes the connection string to point to his SQL Server instance instead of the SQL Server local DB:

App Settings JSON Location

Connection String In App Settings

"Server=(localdb)\\mssqllocaldb;Database=aspnet-SaturdayMP.BuddiesGameTracker-1CDAB6F6-EB6A-4A5D-B6A9-8CD3DC4B3B07;Trusted_Connection=True;MultipleActiveResultSets=true"
"Server=localhost;Database=BuddiesGameTracker;Trusted_Connection=True;"

Then Bud runs the command to update the database:

Update-Database

 

Update Database Command

Update (Dec 5th, 2018): Added the Bud successfully runs the application section below and changed some text at the end or part 1.

Bud runs the application again and this time when he registers there are no errors and he is successfully registered.

Register Successful After Migration

 

Bud doesn’t care about the underlying database that was created.  Well, that is not true, he does care about it but the same way most of us care about our car engine.  We only care about our care engine if the car won’t start.  If the car gets us from point A to point B then we don’t really care about the engine.

Bud doesn’t do this but because we are omnipotent DBAs (are all DBAs omnipotent?) we will peek behind the curtains at the generated database.  And here it is, a new database with some authentication tables.

Buddies Game Tracker Tables Created

From a developer point of view this is great.  Bud didn’t have to write a single line of SQL.  He didn’t didn’t even have to open up SQL Server, the database was just magically created.

This is just the beginning.  Later Bud will create more tables in code to track what buddies have which played which games.  He will do this without writing DDL and access the data with little to no SQL.

I imagine from a DBAs point of view this is a bit strange.  Don’t you start a new application by creating the database ERD first?  How did Visual Studio create the database?  Is the created database any good?  What about the auto-generated CRUD SQL?  Wait, what about the indexes?

Won't Somebody Please Think of the Indexes

Continue to part two of the talk.  You can find the code for this talk here.  As I said above, this is a rough draft so constructive feedback at chris.cumming@saturdaymp.com is much appreciated.

 

 

Posted in Code Examples, Software Development | Tagged , , , , , | Comments Off on Introduction to Object-Relational Mapping for DBAs – Part 1

XPlugins.iOS.BEMCheckBox 1.4.3 Released

I’m happy to announce the release of XPlugins.iOS.BEMCheckBox 1.4.3.  The main feature of this release is exposing the DidTapCheckBox event in the underlying BEMCheckBox.  You can find a full list of issues fixed in this release here.

The easiest way to get this update is via NuGet:

Install-Package SaturdayMP.XPlugins.iOS.BEMCheckBox -Version 1.4.3 
dotnet add package SaturdayMP.XPlugins.iOS.BEMCheckBox --version 1.4.3 

Subscribe to the DidTapCheckBox event as you would any other C# event:

checkbox.DidTapCheckBox += DidTapCheckBoxEvent;

The event handler looks like:

// Fired before the checkbox animation completes but after the internal
// checkbox settings are updated with the new check/unchecked status (i.e.
// On property is updated).
private void DidTapCheckBoxEvent(object sender, EventArgs eventArgs)
{
  Console.WriteLine("In BeforeCheckBoxClickedEvent which is DidTapCheckBox in BEMCheckBox.");
}

Remember XPlugins.iOS.BEMCheckBox is just an Xamarin wrapper for objective-c BEMCheckBox.  For all the features of the checkbox checkout the BEMCheckBox website.

Thanks, as always, to Boris-Em for creating the excellent BEMCheckBox.

Posted in Software Development | Tagged , , , , | Comments Off on XPlugins.iOS.BEMCheckBox 1.4.3 Released

Happy Holidays and all the Best in 2018!

Wrapped Christmas Presents

Gift wrapping skill is inversely correlated to software development skills.

This morning I made my last shopping trip before Christmas, at least I hope it’s my last trip.

Pro tip: the Costco near us officially opens at 10am but if you show up at 9:45ish they will let you in.  At least they let me in.  Then you can run, grab the salmon, and get out before the hoards descend.

Now the salmon is becoming gravlax and the last of the gifts are wrapped.  All that’s left is to write this blog post.  Actually there are a couple other Christmas chores to finish up but not many and then I can kick back and enjoy the holidays with friends and family.

Please note that kicking back means Saturday Morning Productions will be slow to respond to phone calls, e-mails, etc over the holidays.  We appreciate your understanding.

We hope that you have also wrapped up your Christmas chores and gifts and can enjoy this holiday long weekend.  We also hope you are looking forward to the grande adventures you will have in 2018.

Happy holidays and all the best in 2018!

P.S. – Don’t forget this is the season of sharing.  If you are in a position to do so share some of your good fortune with others.  Like cooking the turkey for your wife while they are at the food bank.

https://soundcloud.com/cbc-radio-one/vinyl-cafe-dave-cooks-the

 

Posted in Fun | Tagged | Comments Off on Happy Holidays and all the Best in 2018!

Today I Learned How to Fix Illegal Characters in Path Error with TeamCity and RealmDB

When building a Xamarin application one step is to build the Android APK file.  This is a MsBuild step in TeamCity that looks like:

TeamCity Create APK Package Build Step

This step generates the following error:

[15:55:53][Source\SmallVictories\SmallVictories.csproj] CopyRealmWeaver
[15:55:53][CopyRealmWeaver] CopyRealmWeaver
[15:55:53][CopyRealmWeaver] Copy
[15:55:53][Copy] Creating directory "*Undefined*Tools".
[15:55:53][Copy] C:\BuildAgent\temp\buildTmp\.nuget\packages\realm.database\2.1.0\build\Realm.Database.targets(28, 5): error MSB3021: Unable to copy file "C:\BuildAgent\temp\buildTmp\.nuget\packages\realm.database\2.1.0\build\..\tools\RealmWeaver.Fody.dll" to "*Undefined*Tools\RealmWeaver.Fody.dll". Illegal characters in path.
[15:55:53][Step 6/8] Error message is logged

Notice the “*Undefined*Tools” in the directory path.  To fix this step you need to add /p:SolutionDir=”/” to the command line.  So now the build step looks like:

TeamCity Create APK Package Build Step Fixed

You can find more about the bug in this GitHub issue and more about the fix in this blog post.

 

Posted in Software Development, Today I Learned | Tagged , , | Comments Off on Today I Learned How to Fix Illegal Characters in Path Error with TeamCity and RealmDB

Overlapping Segments Create Space Time Paradoxes

This post is part of a larger discussion about temporal databases.  Hopefully it stands on it’s own but for more context see the Temporal Database Design page.  You can read the official Wikipedia definition but for our purposes a Temporal Database is a database where you can query for historical data using SQL.  This is work in progress and constructive feedback via e-mail, at chris.cumming@saturdaymp.com, is most appreciated.

In the last Temporal Database post I introduced timelines.  In this post we will talk about the one rule you cannot break:

Timeline segments cannot overlap!

That’s it.  That is the one rule.  Breaking this rule leads to all sorts of problems when you try to actually implement timelines in a database.  Aside from creating problems at the database level it also creates theoretical headaches.  For example, if you have the following in your customer table:

Timelines - Overlapping Segments

What is Chronos’s name on December 20th?  Is it Chronos or Kronos?  That said it is possible for people to have two names at the same time.  We have nicknames, aliases, and the like.  If you need to create a database that supports multiple names, say a police database, you can have an Aliases table that hangs off the Offenders table.  For example:

Timelines - Aliases Table

Chronos has an offender record with the name but also has two timelines in the Alias table with his over names.  Notice that alias table has two timelines, not one segment with overlapping segments.

How you design your temporal database will depend on your business logic but you must remember that there is one rule you can’t break:

When this baby hits 88mph you are going to see some serious $#%!

Sorry, wrong timeline.  I meant:

Timeline segments cannot overlap!

Posted in Software Development | Tagged | Comments Off on Overlapping Segments Create Space Time Paradoxes

Temporal Database Timelines

This post is part of a larger discussion about temporal databases.  Hopefully it stands on it’s own but for more context see the Temporal Database Design page.  You can read the official Wikipedia definition but for our purposes a Temporal Database is a database where you can query for historical data using SQL.  This is work in progress and constructive feedback via e-mail (chris.cumming@saturdaymp.com) is most appreciated.

In a non-temporal database a record dose not change over time.  For example say you have a Contacts table with a name field.

Timelines - Contact Table no History

A record in that table does not change over time.  Record 100 either has the name Chronos of some other name.  If you think of this record from a temporal point of view it’s a record starts at the beginning of time and goes to infinity.  If we where to represent this record using a timeline it would look like:Timelines - Non-Temporal Timeline Example

Now lets make the table effective-temporal.  The technical details of how we do this in the database is not important right now.  For now lets just focus on the timeline.  Say Chronos changes his name to Kronos on January 1, 2017 then our timeline would look like:

Timelines - Temporal Timeline Example

We are going to assume gods aren’t born and don’t die so the timeline still goes from start of time to infinity.  However, the timeline now consists of two segment.  The first segment goes from the start of time to Dec 31, 2016.  The second segment goes from Jan 1, 2017 to infinity.

Notice that the ID does not change.  It’s still 100 in both segments.  Chronos changed his name to Kronos but he is still the same person, er god.

One more example.  In this case lets track where John Doe works as he goes through high school.  Lets start in grade 10 with his first job as a burger flipper.  He works in the weekend as he attends school.  The workplace timeline looks like:

Timelines - John Doe - Grade 10 Job

In the summer John continues to work at Bob’s Burgers but also gets a second job as a life guard at the water park Water Wizz.

Timelines - John Doe - Grade 10 to 11 Summer Jobs

Now John Doe has two timelines one for Bob’s Burgers and one for Water Wizz.  When summer ends John leaves Wizz World but keeps his burger flipping job in Grade 11 so now his employment timelines look like:

Timelines - John Doe - Grade 11 Jobs

Notice that the timeline for Wizz World has ended but Bob’s Burgers continues.  In the summer between grade 11 and 12 John is again hired by Wizz World because he such a good worker.  Now his employment timelines look like:

Timelines - John Doe - Grade 11 to 12 Summer Jobs

One of the challenges when creating a temporal database is deciding when to create new timelines and when to create new segments.  In this case we decided to use the existing Wizz World timeline and add a segment to it.  If the employer stays the same keep the timeline, if the employer is different create a new timeline.

Also notice that the Wizz World timeline has a gap in the segments, which is just fine.  What you can’t have is a timeline with overlapping segments.  You can have timelines that overlap but a timeline can’t have overlapping segments.

Let’s talk more about overlapping segments and other stuff in a future segment.  Ah, time jokes, they never get old.

Posted in Software Development | Tagged | Comments Off on Temporal Database Timelines

Notes on Fixing Incomplete Bitcode Error in TeamCity Automated Objective-c Builds

Notes I took while trying to fix the Incomplete Bitcode error in submission bug.  Not sure if it’s fixed yet as I haven’t tried submitting an app to the App Store yet.  Hopefully someone else will try it and confirm it’s fixed.

In summary when submitting an app to iTunes Connect that has the XPlugins.iOS.BEMCheckBox the user got the following error:

ERROR ITMS-90668: “Invalid Bundle Executable. The executable file ‘InstantApp.BoostOrder.Customer.Touch.app/Frameworks/BEMCheckBox.framework/BEMCheckBox’ contains incomplete bitcode. To compile binaries with complete bitcode, open Xcode and choose Archive in the Product menu.”

For some more background please see the previous post Today I Learned How to Automate Objective-c Builds in TeamCity for more information about how built the BEMCheckBox framework.

Current Build Settings

My build settings for compiling the BEMCheckBox framework look like:

TeamCity BEMCheckBox Current Build Actions

The look the same for compiling for both the device (ARM architecture) and the simulator (x86/x64 architecture).  I started with the build step that compiled the device and after some research I figured the problem was the build actions.  Instead of doing build I should do an archive.

Updating Compile for Device Settings

To create an archive requires change the build from Target-based to Schema-based.  There was a couple other changes required which are outlined below.

TeamCity BEMCheckBox Updated Build Actions

  1. Make sure the project build settings are up to date by clicking the Check/Reparse Project.
  2. Change to Scheme-based.
  3. Set the scheme to BEMCheckBox.
  4. Use the output directory or xCode will put the build god-knows-where.
  5. Change the build action from build to archive.

Did a build and everything compiled.  Lets do the same for the simulator build.

Updating Compile for Simulator Settings

Actually you don’t need to change anything for the simulator build.  You can’t create an archive for simulators.  As usual it took me some time to figure out nothing needs to be done.  Aren’t you glad you are reading this instead of wasting time like I did?

Update Script that Combines the Builds

After compiling for the device and the simulator the builds need to be combined into one package.  In my build this is done via a script and a minor update was required because the path changed when we built the archive for the device.

The current script looks like:

cp -r Sample\ Project/build/Release-iphoneos/BEMCheckBox.framework .
lipo -create -output BEMCheckBox.framework/BEMCheckBox Sample\ Project/build/Release-iphoneos/BEMCheckBox.framework/BEMCheckBox Sample\ Project/build/Release-iphonesimulator/BEMCheckBox.framework/BEMCheckBox

It now looks like:

cp -r build/Release-iphoneos/BEMCheckBox.framework .
lipo -create -output BEMCheckBox.framework/BEMCheckBox build/Release-iphoneos/BEMCheckBox.framework/BEMCheckBox Sample\ Project/build/Release-iphonesimulator/BEMCheckBox.framework/BEMCheckBox

Notice the path for the device build has been changed.  It no longer gets put in the Sample Project folder.  I couldn’t figure out a way to get the paths the same for both build so I just gave up.

Anyway, there are my notes on the changes I did.  Not sure if my changes fixed the orginial problem.  If you use XPlugins.iOS.BEMCheckBox please let me know either way.  Thank you to jjchoo for originally reporting the problem.

Posted in Notes, Software Development | Tagged , , , , | Comments Off on Notes on Fixing Incomplete Bitcode Error in TeamCity Automated Objective-c Builds

Family Vacation is Over

Our family vacation is over and the basement is back open for business.  Actually we where open on Monday but I forgot to remove the digital closed signed.  Sorry about that.

On this trip we visited Hong Kong and Shanghai, spending about a week in each city.  This is our second time to Honk Kong and we got to see and do things we missed on our first visit.  This includes hanging out at a beach and swimming, hiking the highest mountain in Hong Kong, a helicopter ride (sponsored by our daughter who saved her money for a year), and visiting the highest building in Hong Kong.

This was our first time to Shanghai and it contrasts nicely with Hong Kong.  Hong Kong is hilly and the population is concentrated in small pockets on the flatter parts.  Shanghai is flat with less hi-rises.  It reminds me of LA, a flat city that stretches for miles.

We stayed near the historic Old Town and did the usual tourist things like visiting People’s Square, toured The Bund, and looked out over Shanghai half a kilometer in the sky in the Shanghai Tower (the second highest building in the world).

Finally we visited both Hong Kong Disneyland, for a second time, and Shanghai Disneyland.  That means we have visited three of the six Disney Resorts having visited the original Disneyland in California in the past.  We have a family goal to visit all six Disney Resorts before my darling daughter turns 18 to help her become an Imagineer.  That and we really like the Disney parks.

Walt Disney Imagineering Logo

Thank you for your patience during our absence.  We have settled into our normal routine and look forward to serving you with refreshed enthusiasm.

Posted in Uncategorized | Comments Off on Family Vacation is Over